AutoIt を Ruby から使い、それを ocra で EXE 化する
ピンポイントな内容で、あまり他の人の役に立つか分かりませんが、ちょっと調べたので書いておきます。
今回の目的は、「AutoIt を呼び出す Ruby スクリプトを ocra で EXE 化し、制限ユーザーでも実行できるようにする」です。
実現方法
予備知識として、ocra による EXE 化はできる前提です。
準備
- RubyInstaller から Ruby 1.9.3 をダウンロードし、インストールしておきます。また、
bin
ディレクトリにパスを通しておきます。 - 以下のコマンドで ocra をインストールしておきます。
- 続いて AutoIt から AutoIt をダウンロードし、インストールしておきます。
AutoItX/AutoItX3.dll
を Ruby のbin
ディレクトリ以下にコピーしておきます。- 以下の内容を記述した
ruby.exe.manifest
を Ruby のbin
ディレクトリ以下に作成します。
これで事前準備は完了です。
EXE の生成
以下のような sample.rb
を考えます。
これは電卓を起動し、3 + 4
を実行するスクリプトです。電卓のウィンドウを表す文字列は、OS によっては異なるかもしれません。
これをそのまま EXE 化して EXE ファイルを別の実機に持っていっても、AutoItX3.dll
が無いので実行できません。AutoItX3.dll
も別の実機にコピーし、前もって 「regsvr32 AutoItX3.dll
」を実行しておけば可能ですが、これには管理者権限が必要です。
これを回避するために、以下のようなコマンドで EXE 化します。
このようにして生成された EXE ファイルは、制限ユーザーであってもそのまま実行でき、AutoItX3.dll
を呼び出すことができます。
説明と補足
以下は、原理の説明などです。
AutoIt
AutoIt とは、Windows の GUI を自動操作することができるツールのことです。
Windows 上で GUI を含んだツールのテストをしたり、GUI プログラムの定型処理を自動化したりするには、それなりに面倒なことが多いのですが、この AutoIt を使うと、割と楽に自動化できます。
同様なことは、.NET からだと Windows 標準の UI Automation などでも可能です。
この AutoIt には、COM インターフェースも用意されており、 COM オブジェクトにアクセスできる言語からは、自由に機能を利用することができます。
実体は AutoItX3.dll
で、AutoItX3.Control
という ProgID でアクセスできます。
もちろん Ruby からも WIN32OLE を利用することで、呼び出すことができます。
上に書いたように、例えば Windows の電卓 (calc.exe) を起動し、3+4 を計算させる場合は、以下のようになります。
ただし、このスクリプトを実行できるようにするためには、AutoItX3.dll
をあらかじめ Windows に登録する必要があります。
インストーラでインストールした場合は登録されているはずですが、自己解凍形式でインストールした場合は、以下のコマンドを管理者権限で実行し、AutoItX3.dll
を Windows に登録しておかなければなりません。
EXE 化して実行するときの問題点
上記の Ruby スクリプトを ocra で EXE 化した場合、その EXE を実行する Windows マシンにも AutoItX3.dll
がインストール済みでなければなりません。これは多少面倒ですし、管理者権限も必要になってしまいます。
今回の本題は、そのあたりをどうするかについてです。
基本的には、ocra で EXE 化する際に AutoItX3.dll
も EXE に含めてしまい、かつスクリプトの内部から制限ユーザーでも呼び出せるようにするということになります。
マニフェストファイル
大きな流れとしては、AutoItX3.dll
を EXE の中に組込み、かつマニフェストファイルを作成することで、その DLL ファイルを COM としてアクセスできるようにしてやる、ということになります。
マニフェストファイルとは、EXE ファイルのメタ情報のようなもので、ロードすべき DLL を指定したり、UAC 昇格が必要であることを指定したりする XML ファイルです。
このファイルを用いて、AutoItX3.dll
の中に AutoItX3.Control
という ProgID の COM オブジェクトがあることを明示し、ruby.exe からアクセスできるようにしてやります。
このマニフェストファイルは、実行する EXE に .manifest
をつけた名前にします。
ocra では、ruby.exe
やその他の DLL を Temp ディレクトリに展開し、その後 ruby.exe
を実行します。
そのため、Temp ディレクトリに展開される際に、マニフェストファイルも展開されるようにすれば、ruby.exe
が実行される際にマニフェストファイルで COM 用 DLL を指定することができます。
そのため、以下のようなコマンドで EXE ファイルを作成すれば、AutoItX3.dll
も ruby.exe.manifest
も ruby.exe
と同じディレクトリに展開されるようになります。
これで、制限ユーザーであっても、AutoItX3.dll
がインストールされていない状況であっても、Ruby スクリプトから AutoIt の COM インターフェースにアクセスできる EXE ができあがります。
ポイント
--dll
を使っているところがポイントです。
前提として、ocra で EXE 化されたスクリプトは、まず一時フォルダに ruby.exe 本体やスクリプトや DLL などを展開し、さらに展開した ruby プログラムを実行する、という二段構成になっています。
細かく書くと、EXE を実行すると、ruby.exe 本体が置かれる bin
ディレクトリ、ライブラリが置かれる lib
ディレクトリ、ユーザーのソースコードが置かれる src
ディレクトリの三つをそれぞれ展開し、その後 src
以下のソースコードを bin
ディレクトリ以下の ruby.exe によって実行する、という流れになります。
EXE 作成時に --dll
オプションを使って指定されたファイルは、EXE 実行時に bin
ディレクトリ以下に展開されることになります。
そのため、上の例では、EXE 実行時には以下のような配置になります。
- /
-
- bin
- ruby.exe
- AutoItX3.dll
- ruby.exe.manifest
-
- lib
- require されたライブラリが配置される。
-
- src
- sample.rb
上のように ruby.exe.manifest ファイルを配置することで、展開された ruby.exe が実行される際に、ruby.exe.manifest を読み込ませることができ、結果として AutoItX の COM インターフェースにアクセスできるようになります。
ちなみに、ocraruby として一つのバイナリにまとめてある Ruby の中にも、同様の仕組みで AutoItX3.dll
を組み込んであります。
というわけで、何回か仕事で使うツールの内容が続きましたが、忙しかった時期も過ぎつつあり、そろそろこの週末ぐらいからは mruby を触れそうです。
AutoItを楽に別のところで使いたいと思っていまして、ちょうどピンポイントな内容で解決できました。ありがとうございます。
返信削除そこで質問なのですが、TEMPフォルダに展開されたファイルって自動で消すことってできないでしょうか?実行するたびにどんどん増えていくので困っています。現在は別ツールで消してもらうようにしていますが、できればひとつのプログラム内で解決できたらと思っています。何か解決策はありますでしょうか?
> TEMPフォルダに展開されたファイルって自動で消すことってできないでしょうか?
返信削除普通のスクリプトでは、ocraが消してくれると思います。
実際に消えない時のサンプルソースなどはありますか?
お早い対応に対して遅い返信申し訳ありません。
削除確かめたところ確かにちゃんと消えているようです。これまでは×ボタンで終了させてることが多かったので、消えないものだと思い込んでいたようです。正常終了することで一応解決しそうです。
ありがとうございました。