Qiita初投稿です。
概要
Windows Script Host(WSH)はWindowsに標準搭載されたスクリプト実行環境です。
心臓部にEdge(Legacy)に搭載されたJavaScriptエンジンであるChakraを利用することで、ES2015相当の言語機能を利用することができます。
Chakraを常用するベストプラクティスを探っています。
- CLSIDは覚えられない
- 職場など管理者権限のない環境でも設定できる
- 他人の環境でも動く
- ダブルクリックで実行できるWSHの利点を損ないたくない
- 将来的にTypeScriptで書きたい
など...
環境
- Windows10
私の環境で試していること
- コンソールから実行する用に、バッチにPATHを通す
- ダブルクリックで実行できる機構は「おまじない」に任せる
- レジストリ編集は補助的に利用
この記事のコードは、GitHubに置いています。
バッチにPATHを通す
以下3つのバッチファイルを作成し、PATHを通します。
WChakra.bat
, CChakra.bat
はそれぞれwscript, cscriptを司り、Chakra.bat
はデフォルトがどちらか調査して適当に振り分けます。
コマンドラインからchakra hoge.js
wchakra fuga.js
などで利用できるほか、既定のアプリケーションに登録することもできます。
良いところ
- 特にコンソールから実行する場合にわかりやすい
- 拡張子に関連付けして、ダブルクリックで実行できる
微妙なところ
- バッチは普段書かないので改善点があるかも(逐次修正)
-
Chakra.bat
はほんの少し遅いので、大量にキックする用途だと厳しそう -
WChakra.bat
をダブルクリックで実行中にはDOS窓が表示される
@echo off
setlocal
set fn=%~dp0\_.vbs
REM this one-liner returns 0 only if hosted by "wscript.exe"
echo If(LCase(WScript.CreateObject("Scripting.FileSystemObject").GetFileName(WScript.FullName))="wscript.exe")Then:ret=0:Else:ret=1:WScript.Quit(ret) > %fn%
%fn% > nul 2>&1
if %errorlevel% equ 0 (
del %fn%
WChakra %*
) else (
del %fn%
CChakra %*
)
exit /b %errorlevel%
@echo off
if not "%~1"=="" (
wscript //E:{1B7CD997-E5FF-4932-A7A6-2A9E636DA385} %*
) else (
wscript
)
exit /b %errorlevel%
@echo off
if not "%~1"=="" (
cscript //E:{1B7CD997-E5FF-4932-A7A6-2A9E636DA385} %*
) else (
cscript
)
exit /b %errorlevel%
冒頭に「おまじない」を書く
こちらを参考にさせていただきました。
ダブルクリックまたはドラッグアンドドロップで利用できます。
変更点
- 文字数を絞る
- 生成される一時ファイルを隠しファイルに変更
- コマンドライン引数対応
- WScriptとCScriptを判別してキック
良いところ
- 冒頭(と末尾)に記載するだけ、手軽
- 他人の環境でも動く
微妙なところ
- 現状CScriptの標準入力は利用できない
/*@cc_on
w=WScript;
st=w.CreateObject("ADODB.Stream");
fs=w.CreateObject("Scripting.FileSystemObject");
sh=w.CreateObject("WScript.Shell");
fn=w.ScriptFullName;
// 自身の文字コードをShift-JISに変換した一時ファイルを作成する
st.Charset="UTF-8";
st.Open();
st.LoadFromFile(fn);
t=st.ReadText();
st.Close();
fn=fs.GetFile(fn).ParentFolder.Path+"\\."+w.ScriptName;
if(fs.FileExists(fn))fs.DeleteFile(fn,true);
st=fs.CreateTextFile(fn);
f=fs.GetFile(fn);
f.Attributes=2;
st.Write(t);
st.Close();
// コマンドライン引数を引き継ぐ
arg=w.Arguments;
opt="";
for(i=0;i<arg.Count();i++){
opt+=" \""+arg.Item(i)+"\"";
}
opt=opt.slice(1);
// キック
host=w.FullName;
cmd=host+" //Nologo //E:{1B7CD997-E5FF-4932-A7A6-2A9E636DA385} \""+fn+"\" "+opt;
if(fs.GetFileName(host).toLowerCase()=="wscript.exe"){
ret=sh.Run(cmd,1,true);
}else{
ex=sh.Exec(cmd);
while(ex.Status==0){
try{
w.StdOut.Write(ex.StdOut.Read(1));
}catch(e){}
}
ret=ex.ExitCode;
w.StdOut.Write(ex.StdOut.ReadAll());
}
f.Delete(true);
w.Quit(ret);
@if(0)*/
// 本体ここから
const args = WScript.Arguments;
let msg = "";
for(let i = 0; i < args.Count(); i++){
msg += `${args.Item(i)}\n`;
}
WScript.Echo(msg);
//@end
/*@cc_on;w=WScript;st=w.CreateObject("ADODB.Stream");fs=w.CreateObject("Scripting.FileSystemObject");sh=w.CreateObject("WScript.Shell");fn=w.ScriptFullName;st.Charset="UTF-8";st.Open();st.LoadFromFile(fn);t=st.ReadText();st.Close();fn=fs.GetFile(fn).ParentFolder.Path+"\\."+w.ScriptName;if(fs.FileExists(fn))fs.DeleteFile(fn,true);st=fs.CreateTextFile(fn);f=fs.GetFile(fn);f.Attributes=2;st.Write(t);st.Close();arg=w.Arguments;opt="";for(i=0;i<arg.Count();i++){opt+=" \""+arg.Item(i)+"\"";}opt=opt.slice(1);host=w.FullName;cmd=host+" //Nologo //E:{1B7CD997-E5FF-4932-A7A6-2A9E636DA385} \""+fn+"\" "+opt;if(fs.GetFileName(host).toLowerCase()=="wscript.exe"){ret=sh.Run(cmd,1,true);}else{ex=sh.Exec(cmd);while(ex.Status==0){try{w.StdOut.Write(ex.StdOut.Read(1));}catch(e){}}ret=ex.ExitCode;w.StdOut.Write(ex.StdOut.ReadAll());}f.Delete(true);w.Quit(ret);@if(0)*/
レジストリを編集する
こちらを参考にさせていただきました。
wscript //E:Chakra hoge.js
で利用できるようになります。
良いところ
- wsfでも利用できる(はず、確認出来たら追記)
- CLSID直書きでもできるかも
微妙なところ
- 他所の環境では動かない
- レジストリいじるときは慎重に
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Chakra]
@="Chakra Language"
[HKEY_CLASSES_ROOT\Chakra\CLSID]
@="{1b7cd997-e5ff-4932-a7a6-2a9e636da385}"
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\SOFTWARE\Classes\Chakra]
@="Chakra Language"
[HKEY_CURRENT_USER\SOFTWARE\Classes\Chakra\CLSID]
@="{1b7cd997-e5ff-4932-a7a6-2a9e636da385}"
機能制限について補足
Chakra利用時にWScript.Quit()
が利用できないため、終了コードを返せないとのことなので実験しました。
1~6の整数を終了コードにセットするJavaScriptを用意して、10回実行します。
PowerShellでは、$LastExitCode
に直前の終了コードが代入されます。
エラーが発生するため、握り潰します。
try {
WScript.Quit(parseInt(6 * Math.random() + 1));
} catch (e) {
// JavaScript runtime error: Object doesn't support this action
}
> for($i=0; $i -lt 10; $i++){chakra dice.js; echo $LastExitCode;}
1
4
5
6
5
2
4
1
3
2
きちんとランダムです。
エラーが発生し停止もしませんが、なぜか終了コードは返せているようです。
参考
- WSH JScript Chakra を使用した ES2015(ES6) 対応 ( スクリプトエンジン まとめ )
- WSH JScript Chakra エンジンの共存による機能制限の回避(WScript Quit 代替)
- Chakraエンジン対応のWSHスクリプトをダブルクリックで実行できるようにする
- ScriptControlでChakra使う
随時更新...