IronPython, IronRuby での Silverlight 4 におけるブラウザー外実行と COM 連携 - WshShell でメモ帳を起動
IronPython, IronRuby で実装した Silverlight 4 にて、ブラウザー外実行時の COM オートメーション連携機能を試してみました。(ただし、IronRuby の方は正常動作しなかった)
使用した環境は以下の通り。
- IronPython 2.7A1
- IronRuby 1.1.1
なお、COM オートメーション連携機能は WshShell(WScript.Shell)を使ったメモ帳の起動を試してみました。
サンプルのソースコードは http://github.com/fits/try_samples/tree/master/blog/20101109/
個人的には、COM オートメーション連携が必要になっている時点でマルチプラットフォームを普通考慮しないだろうし、今回のようなケースで Silverlight にするメリットってそれほど無い気がしてますが・・・。
プロジェクトの雛形作成
まず、IronPython や IronRuby それぞれのホームディレクトリの Silverlight\script\sl.bat を使ってプロジェクトの雛形を作成します。
Silverlight\script\templates 内のファイルをコピーしてくるだけのようなので手動でコピーしてきてもいいと思います。
作成するプロジェクトのディレクトリを wsh_sample とすると以下のようになります。
IronPython の場合
> sl.bat python wsh_sample
COM オートメーション連携機能実装
app.py(もしくは app.rb)にボタンが押された際に WshShell を使ってメモ帳(notepad.exe)を起動する処理を実装します。
COM オートメーションの progID を AutomationFactory.CreateObject(もしくは GetObject)に指定して COM オブジェクトを取得し、メソッドを実行することになります。
また、AutomationFactory.IsAvailable を使って COM オートメーション連携機能が有効な状況か否かをチェックする事ができます。
なお、COM オートメーション連携を行うには、後述する AppManifest.xaml での昇格された信頼の設定が必要となります。(その設定が無いと IsAvailable が true にならない)
app.py(IronPython の場合)
from System.Windows import * from System.Windows.Controls import UserControl from System.Runtime.InteropServices.Automation import AutomationFactory class App: def __init__(self): root = Application.Current.LoadRootVisual(UserControl(), "app.xaml") root.Message.Text = "Notepad Sample" root.NotepadButton.Content = "Run Notepad" root.NotepadButton.Click += self.button_click def button_click(self, sender, e): if AutomationFactory.IsAvailable: try: wsh = AutomationFactory.CreateObject("WScript.Shell") wsh.Run("notepad.exe") except Exception as e: MessageBox.Show("Error: " . e) else: MessageBox.Show("AutomationFactory: NG") App()
app.rb(IronRuby の場合)
include System::Windows include System::Windows::Controls include System::Runtime::InteropServices::Automation class App def initialize @root = Application.current.load_root_visual(UserControl.new, "app.xaml") @root.find_name('Message').text = "Notepad Sample" btn = @root.find_name('NotepadButton') btn.content = "Run Notepad" btn.Click {|sender, e| if AutomationFactory.IsAvailable begin wsh = AutomationFactory.CreateObject("WScript.Shell") #Run メソッドは正常に実行されない(例外も発生せず落ちている模様) r = wsh.Run("notepad.exe") rescue => e MessageBox.Show("Error: " + e) end else MessageBox.Show("AutomationFactory: NG") end } end end $app = App.new
IronRuby の方は正常に動作しなかったのですが、以下のようなコードだと問題なく動作するので COM オートメーション連携が全く機能しないという事では無さそうです。
IronRuby で実行に成功した COM オートメーション連携
wsn = AutomationFactory.CreateObject("WScript.Network") MessageBox.Show(wsn.ComputerName)
ちなみに、app.xaml は以下のとおりです。
app.xaml
<UserControl x:Class="System.Windows.Controls.UserControl" xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <StackPanel x:Name="layout_root" Background="White"> <TextBlock x:Name="Message" FontSize="30" /> <Button x:Name="NotepadButton" Height="50" /> </StackPanel> </UserControl>
ブラウザー外実行用の AppManifest.xaml 作成
ブラウザー外実行の設定 Deployment.OutOfBrowserSettings を施した AppManifest.xaml ファイルを app ディレクトリに作成します。
注意点
ただし、ブラウザー外実行をしない場合や Chiron.exe.config ファイルでブラウザー外実行設定のコメントアウトを外した場合等では、AppManifest.xaml を自前で用意する必要はありません。(Chiron.exe で xap ファイルを作成する際に自動的に用意してくれる)
なお、COM オートメーション連携を行うには以下の設定が必要になります。
COM オートメーション連携を使う場合の昇格された信頼設定
<OutOfBrowserSettings.SecuritySettings> <SecuritySettings ElevatedPermissions="Required" /> </OutOfBrowserSettings.SecuritySettings>
IronPython の場合は以下のようになります。
AppManifest.xaml(IronPython の場合)
<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" RuntimeVersion="2.0.31005.0" EntryPointAssembly="Microsoft.Scripting.Silverlight" EntryPointType="Microsoft.Scripting.Silverlight.DynamicApplication" ExternalCallersFromCrossDomain="ScriptableOnly"> <!-- Add assembly references here --> <Deployment.Parts> <AssemblyPart Source="Microsoft.Scripting.Silverlight.dll" /> <AssemblyPart Source="System.Numerics.dll" /> <AssemblyPart Source="Microsoft.Scripting.dll" /> <AssemblyPart Source="Microsoft.Dynamic.dll" /> <AssemblyPart Source="IronPython.dll" /> <AssemblyPart Source="IronPython.Modules.dll" /> </Deployment.Parts> ・・・ <!-- ブラウザー外実行の設定 --> <Deployment.OutOfBrowserSettings> <OutOfBrowserSettings ShortName="DLR Application" EnableGPUAcceleration="False" ShowInstallMenuItem="True"> <OutOfBrowserSettings.Blurb> DLR Application </OutOfBrowserSettings.Blurb> <OutOfBrowserSettings.Icons /> <OutOfBrowserSettings.WindowSettings> <WindowSettings Title="DLR Application" Height="200" Width="300" /> </OutOfBrowserSettings.WindowSettings> <OutOfBrowserSettings.SecuritySettings> <!-- COMオートメーション連携機能を使うための設定 --> <SecuritySettings ElevatedPermissions="Required" /> </OutOfBrowserSettings.SecuritySettings> </OutOfBrowserSettings> </Deployment.OutOfBrowserSettings> </Deployment>
IronRuby の場合は、基本的に上記の IronPython.dll・IronPython.Modules.dll が IronRuby.dll・IronRuby.Libraries.dll に変わるだけです。
ビルド
ビルドは IronPython・IronRuby の Silverlight\bin\Chiron.exe を使って、xap ファイルを作成するだけです。
ビルド(IronPython, IronRuby 共通)
> Chiron.exe /d:app /z:wsh_sample.xap
動作確認
sllauncher.exe に /emulate オプションを指定すればインストールを行わずに動作確認が行えます。
なお、/origin で URI を指定する必要があるので適当に指定します。
sllauncher.exe は、C:\Program Files\Microsoft Silverlight(もしくは C:\Program Files (x86)\Microsoft Silverlight)にあると思います。
動作確認(IronPython, IronRuby 共通)
> sllauncher.exe /emulate:wsh_sample.xap /origin:file:///
IronPython の方は「Run Notepad」ボタンを押下するとメモ帳が起動しますが、
IronRuby の方は「Run Notepad」ボタンを押下した際にボタン表示等が消えてしまうと思います。
追記
以下のように Silverlight では無く通常の IronRuby スクリプトとしてメモ帳の起動を行ってみたところ正常に動作しました。
wsh_run.rb
include System wsh = Activator.CreateInstance(Type.GetTypeFromProgID("WScript.Shell")) wsh.Run("notepad.exe")
実行例
> ir wsh_run.rb