x64には存在しないScriptControlの代わり
以前、こんな記事を書いた。
x64には存在しないScriptControlの代わり - じゅんじゅんのきまぐれ
この時、ieのプロセスができちゃうなー、と思っていて、.Net JScriptの方法も書いたけど、ieのプロセスを作りたくなかったら、htmlfileを使えば良いことに今頃気づいたので、書いてみた。
ま、大して意味がないけど、Disposeしなくて良いのが利点か。
ただ、ie依存だと、x86とx64の橋渡しなんてこともできるんだよね。
スクリプト
これ、scriptをJScriptで書いてるからJScript版だけど、VBScriptで書けばVBScriptが動く、、、はず。
$js = New-Object PSObject $js | Add-Member NoteProperty "hd" (New-Object -ComObject htmlfile) $js.hd.IHTMLDocument2_write(@" <html><head> <meta http-equiv='X-UA-Compatible' content='IE=edge' /> <title>htmlfile for powershell</title> <script> document.__js = { eval: function(code, p) { var ret = null try { ret = eval(code) } catch(e) { this.lastErrNo = e.number this.lastErrMsg = e.description throw e } return ret; }, get: function(obj, name) { return obj[name] }, set: function(obj, name, val) { obj[name] = val }, getAttrs: function(obj) { var ret = '' for(var a in obj) ret += ',' + a return ret.substr(1) }, parse: function(str) { return JSON.parse(str) }, stringify: function(obj, ind) { return JSON.stringify(obj, null, ind) } } </script> </head><body></body></html> "@) $js | Add-Member NoteProperty "e" ([System.__ComObject].InvokeMember("__js", [System.Reflection.BindingFlags]::GetProperty, $null, $js.hd, $null)) $js | Add-Member ScriptMethod "Eval" { if($args.length -gt 0) { $para = $null if($args.length -gt 1) { $para = $args[1] } $this.e.eval($args[0], $para) } } $js | Add-Member ScriptMethod "Get" { $ret = $null if($args.length -gt 1) { $ns = $args[1] if($ns -isnot [Array]) { $ns = $ns -split '\.' } $len = $ns.Length $ret = $this.e.get($args[0], $ns[0]) if($args.length -gt 2 -and $args[2] -and $ret -eq $null) { $ret = $this.e.eval("({})", $null) $this.e.set($args[0], $ns[0], $ret) } if($len -gt 1) { $ret = $this.Get($ret, $ns[1..($len-1)]) } } return $ret } $js | Add-Member ScriptMethod "Set" { if($args.length -gt 2) { $ns = $args[1] if($ns -isnot [Array]) { $ns = $ns -split '\.' } $len = $ns.Length if($len -gt 1) { $add = $true if($args.length -gt 3) { $add = $args[3] } $this.e.set($this.Get($args[0], $ns[0..($len-2)], $add), $ns[($len-1)], $args[2]) } else { $this.e.set($args[0], $args[1], $args[2]) } } } $js | Add-Member ScriptMethod "List" { $ret = @{} if($args.length -gt 0) { $tar = $args[0] if($args.length -gt 1) { $tar = $this.Get($tar, $args[1]) } $as = $this.e.getAttrs($tar) -split "," foreach($a in $as) { $val = $this.Get($tar, $a) #if($val -is [__ComObject]) { $val = $this.List($val) } $ret.Add($a, $val) } } return $ret } $js | Add-Member ScriptMethod "Run"{ if($args.length -gt 1) { $obj = $null if($args.length -gt 2) { $obj = $args[2] } $ns = $args[1] if($ns -isnot [Array]) { $ns = $ns -split '\.' } $len = $ns.Length if($len -gt 1) { ([System.__ComObject].InvokeMember($ns[($len-1)], [System.Reflection.BindingFlags]::InvokeMethod, $null, $this.Get($args[0], $ns[0..($len-2)]), $obj)) } else { [System.__ComObject].InvokeMember($args[1], [System.Reflection.BindingFlags]::InvokeMethod, $null, $args[0], $obj) } } }
詳しく、、、もないけどある程度は、
x64には存在しないScriptControlの代わり - じゅんじゅんのきまぐれ
を参照してください。
使用例
上のスクリプトを実行した後で、、、。
とりあえずスクリプトを実行したい場合
PS> $js.Eval('escape("ああん?")') %u3042%u3042%u3093%uFF1F PS> $js.Eval("unescape('%u3042%u3042%u3093%uFF1F')") ああん?
実行の際、引数を渡したいなら
PS> $js.Eval('p * 3', 12) 36
第二引数がpとして参照できます。
JScriptオブジェクトを作るなら
PS> $jsobj = $js.e.parse('{"p1":12115,"p2":"testtest"}') PS> $jsobj System.__ComObject PS> $js.e.stringify($jsobj, 2) { "p1": 12115, "p2": "testtest" }
作ったオブジェクトの要素一覧
PS> $js.List($jsobj) Name Value ---- ----- p1 12115 p2 testtest
オブジェクトの値を設定・取得したいなら
PS O:\> $js.Set($jsobj, 'p1', 12116) PS O:\> $js.Get($jsobj, 'p1') 12116