イネマルのプログラミング備忘録

趣味プログラマのメモ

JScript.NET をバッチに埋め込む方法

はじめに

Microsoft製のドマイナー言語、JScript .NET をバッチファイルに埋め込んで実行する方法です。

JScript .NET は、スクリプト言語である WSHJScript の後継的な位置づけでありながら、コンパイル必須という扱いづらい言語なので、
コンパイル処理と実行を一度に処理できるように、バッチファイルに埋め込んでしまおうというお話。

実装

おまじない部分

バッチに埋め込んで実行するためのコード。
コンパイルに成功したら実行するだけ。

@if(0)==(0) for /f "delims=" %%i in ('where /r %windir%\Microsoft.NET jsc.exe^|sort') do @set jsc=%%i
@"%jsc%" /nologo /out:"%~dp0%~n0.exe" "%~f0"&&"%~dp0%~n0.exe" %*
@exit /b&@end

バッチをUTF-8で保存する場合

コンパイラ文字コードを知らせるため、/codepage オプションを指定します。
UTF-8のコードページは、65001です。

@"%jsc%" /nologo /codepage:65001 /out:"%~dp0%~n0.exe" "%~f0"&&"%~dp0%~n0.exe" %*

多重コンパイルしたくない場合

実行毎にコンパイルが走ると、その分起動に時間がかかってしまうので、
実行ファイル名にハッシュ値を入れて、コンパイルが必要かどうか判定します。

@if(0)==(0) echo off&for /f "delims=" %%i in ('certutil -hashfile "%~f0"^|find /v ":"') do set app_path=%~dp0%~n0[%%i].exe
if not exist "%app_path%" del "%~dp0%~n0[*].exe">nul 2>&1&for /f "delims=" %%i in ('where /r %windir%\Microsoft.NET jsc.exe^|sort /r') do "%%i" /nologo /out:"%app_path%" "%~f0"&&goto:run||pause&goto:EOF
:run
"%app_path%" %*&exit /b &@end

// 以下に実装を書く
import System;

/**
 * エントリーポイント用
 */
Environment.Exit(function():int{
    var exitCode:int = 123;
    try{
        Console.WriteLine("Hello JScript.NET!!");
        Console.ReadKey();
    }catch(e){
        exitCode = int.MaxValue;
        print(e), Console.ReadKey();
    }finally{
    }
    return exitCode;
}());

その他

別解として、
実行ファイルを作らず powershell 経由でインメモリ実行する例。 qiita.com