ScriptControlの利用
2008年7月4日
先日とりあげた、wscript.exe用のマニフェストを書く方法に加えて、ScriptControlを利用する方法も試してみた。とりあえず、VB(VB5)を用いて簡単に作成したプログラムのソースコードは次のとおり。
oyagame.exeという名でexeファイルを作成し、oyagame.exe.manifestを先の記事と同様に作成すると、このexeを解してJScriptのコードが動くことを確認。ただし、JScriptをwscript.exeで実行したときに使えるWScriptオブジェクトは使えないらしい。これがVBScript/JScriptでプログラムを書くときにどれくらい支障をきたすかは、良く分からない。ちょっと考えた感じだと、WScript.Quit()が使えないのは痛いかも。
ところで、JScript.NETも試してみたけれど、今のままではoyagameでは使えない(使いにくい)ことが分かった。その理由は、eval(SDL.ConstJS); で定義する定数が、JScript.NETでは使えないこと。もし需要があるのなら、JScript.NETで使えるようにすること、考えてみたい。
Option Explicit Sub Main() Dim cmdLine As String cmdLine = LCase(Command) If Len(cmdLine) = 0 Then End If Right(cmdLine, 1) = """" Then cmdLine = Left(cmdLine, Len(cmdLine) - 1) Dim isVBScript As Boolean, isEncoded As Boolean isEncoded = (Right(cmdLine, 1) = "e") isVBScript = (Left(Right(cmdLine, 3), 2) = "vb") Dim Lang As String If isVBScript Then Lang = "vbscript" Else Lang = "jscript" End If If isEncoded Then Lang = Lang & ".encode" Dim Code As String, buff As String Code = "" Open Command For Input As #1 Do Until EOF(1) Line Input #1, buff Code = Code + buff + vbCrLf Loop Dim sc Set sc = CreateObject("ScriptControl") sc.language = Lang sc.executestatement Code End Sub
oyagame.exeという名でexeファイルを作成し、oyagame.exe.manifestを先の記事と同様に作成すると、このexeを解してJScriptのコードが動くことを確認。ただし、JScriptをwscript.exeで実行したときに使えるWScriptオブジェクトは使えないらしい。これがVBScript/JScriptでプログラムを書くときにどれくらい支障をきたすかは、良く分からない。ちょっと考えた感じだと、WScript.Quit()が使えないのは痛いかも。
ところで、JScript.NETも試してみたけれど、今のままではoyagameでは使えない(使いにくい)ことが分かった。その理由は、eval(SDL.ConstJS); で定義する定数が、JScript.NETでは使えないこと。もし需要があるのなら、JScript.NETで使えるようにすること、考えてみたい。
コメント
Kat (2008年7月6日 16:40:12)
上記コードはVBを用いて書かれているけれど、C++を用いたスタンドアローンなEXEの製作もほぼめどがついた。
あとは、WScriptオブジェクトをいかにサポートするかだ。たぶん、次のメソッド・プロパティのサポートでよい。
Arguments
Path
Name
FullName
ScriptName
ScriptFullName
CreateObject
Echo
Quit
Sleep
あとは、WScriptオブジェクトをいかにサポートするかだ。たぶん、次のメソッド・プロパティのサポートでよい。
Arguments
Path
Name
FullName
ScriptName
ScriptFullName
CreateObject
Echo
Quit
Sleep
Kat (2008年7月8日 12:57:07)
MicrosoftのScriptControlのダウンロードサイトによると、Win2000以降はデフォルトでScriptControlが含まれているようだ。なら、manifestを利用したoyagameの実行にScriptControlを使うのは問題ないことになる(XP以降が必要なので)。
http://www.microsoft.com/downloads/details.aspx?FamilyID=151ef63d-23e9-4367-bb25-37310c6222fe&displaylang=ja
http://www.microsoft.com/downloads/details.aspx?FamilyID=151ef63d-23e9-4367-bb25-37310c6222fe&displaylang=ja
Kat (2008年7月9日 18:06:36)
WScript.Quit()の実装は、この辺が参考になりそう。
http://www.microsoft.com/japan/technet/scriptcenter/resources/qanda/sept04/hey0927.mspx
スクリプト中で自身のプロセスIDを取得するのはトリッキーのよう(新たなプロセスを開始して、その親プロセス(自身)のIDをWMIで取得)なので、自身のプロセスIDはEXE中で取得しておいて、スクリプトを動的に書き出せばよいだろう。
http://www.microsoft.com/japan/technet/scriptcenter/resources/qanda/sept04/hey0927.mspx
スクリプト中で自身のプロセスIDを取得するのはトリッキーのよう(新たなプロセスを開始して、その親プロセス(自身)のIDをWMIで取得)なので、自身のプロセスIDはEXE中で取得しておいて、スクリプトを動的に書き出せばよいだろう。
Kat (2008年7月9日 18:54:29)
Warning: comments::cb1_tag_body(): Argument #1 ($m) must be passed by reference, value given in /home/u109394186/domains/rad51.net/public_html/jeans/jeans/libs/comments.php on line 51
Warning: comments::cb1_tag_body(): Argument #1 ($m) must be passed by reference, value given in /home/u109394186/domains/rad51.net/public_html/jeans/jeans/libs/comments.php on line 51
Warning: comments::cb1_tag_body(): Argument #1 ($m) must be passed by reference, value given in /home/u109394186/domains/rad51.net/public_html/jeans/jeans/libs/comments.php on line 51
WScript.Sleep()の実装は、この辺。
http://sakura.qp.land.to/?Macro%2F%C5%EA%B9%C6%2F188
t=timer
mSec=100
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
set temp=objWMIService.ExecNotificationQuery _
("select * from __instancecreationevent within 1" _
& " where targetinstance isa 'Win32_Process'" _
& " and targetinstance.ProcessID=0")
On Error Resume Next
temp.NextEvent mSec
msgbox timer-t & vbcrlf & err.description
Kat (2008年7月9日 19:53:59)
ScriptControlを使えば、manifestを用いなくてもCOMオブジェクトが使えそうな方法を思いついたので、忘れないうちにメモ。Win2000/NTでもOKのはず。
1)EXEを起動
2)EXEで、oyagame.dllをロード
3)EXEでは、ロードしたoyagameからオブジェクトを取得するための簡単なIDispatchクラスを記述しておく
4)ScriptControlオブジェクトを作成
5)ScriptControlに、関数を一つ登録(AddCode)。この関数は、上記IDIspatchクラスインスタンスをグローバル変数に割り当てるためのもの。
6)ScriptContorlに、関数を一つ登録。この関数は、上記IDIspatchクラスインスタンス(グローバル変数に割り当てられている)から、oyagameオブジェクトを取得するためのもの。
7)最後に、コードを、ExecuteStatementする。6)で登録した関数から、oyagameオブジェクトを取得可能。
1)EXEを起動
2)EXEで、oyagame.dllをロード
3)EXEでは、ロードしたoyagameからオブジェクトを取得するための簡単なIDispatchクラスを記述しておく
4)ScriptControlオブジェクトを作成
5)ScriptControlに、関数を一つ登録(AddCode)。この関数は、上記IDIspatchクラスインスタンスをグローバル変数に割り当てるためのもの。
6)ScriptContorlに、関数を一つ登録。この関数は、上記IDIspatchクラスインスタンス(グローバル変数に割り当てられている)から、oyagameオブジェクトを取得するためのもの。
7)最後に、コードを、ExecuteStatementする。6)で登録した関数から、oyagameオブジェクトを取得可能。
Kat (2008年7月12日 00:12:19)
上記コメントの5)は、以下の例のように実装可。
set sc=WScript.CreateObject("ScriptControl")
sc.language="VBScript"
sc.addcode "dim sc2"
sc.addcode "sub test(obj) set sc2=obj end sub"
sc.run "test",sc
sc.executestatement "msgbox sc2.language"
ScriptControlオブジェクト中のグローバル変数『sc2』に、『sc』というオブジェクトへの参照を渡している。同じことは、C++で書いたEXE中でも可能のはず。
set sc=WScript.CreateObject("ScriptControl")
sc.language="VBScript"
sc.addcode "dim sc2"
sc.addcode "sub test(obj) set sc2=obj end sub"
sc.run "test",sc
sc.executestatement "msgbox sc2.language"
ScriptControlオブジェクト中のグローバル変数『sc2』に、『sc』というオブジェクトへの参照を渡している。同じことは、C++で書いたEXE中でも可能のはず。