Ever since I read Don's post the other day pointing out the often-overlooked support for a powerful command-line scripting languge in Windows (Javascript), I've been meaning to post this. It's a batch file that will let you run JScript.NET files interactively. Since Javascript is a compiled language, it does this by compiling it to a temporary directory first and then running the compiled EXE. While this might sound slow, as it turns out it's quite acceptable for quick, scripting-type tasks, and it gives me what I've always wanted: a convenient scripting language with full, natural-sytnax access both to COM and the .NET libraries.
Much as I'd like to claim credit for the batch file, I can't. It was written by John Elliott (for whom I don't have a URL) and posted to the WinTech Off-Topic List. The only modification I made was to add the /fast- switch to the compile, which turns off “fast mode”. Near as I can tell (not yet being that familiar with JScript.NET), it makes the code somewhat slower, but enables a lot of the more “scripty” features of the language, such as the ability to add methods dynamically to BCL types. Anyway, here's the script. I called mine rjs.cmd, and stuck it in my \bin directory, which is in my path. Then I can launch scripts by simply running “rjs foo.js“.
@echo OFFrem ///////////////////////////////////////////////////////////////////////
rem // js-net-script.cmd
rem // ====================================================================
rem //
rem // Compiles and runs a JScript.NET source file.
rem //
goto :INIT
rem ///////////////////////////////////////////////////////////////////////
rem // HELP procedure
rem // ==============
rem //
rem // Display brief help message
rem //
:HELP
if defined TRACE %TRACE% [proc %0 %*]
echo Compiles and runs a JScript.NET source file as a console application.
echo.
echo JS-NET-SCRIPT script [args]
echo.
echo script Path to the JScript.NET file you wish to compile and run.
echo args Any arguments you wish to pass to the JScript.NET app.
echo.
goto :EOF
rem ///////////////////////////////////////////////////////////////////////
rem // MAIN procedure
rem //
:MAIN
if defined TRACE %TRACE% [proc %0 %*]
rem // make sure our working directory exists.
rem // this is where our build outputs will be stored temporarily.
if not exist "%APPDATA%\js-net-script" mkdir "%APPDATA%\js-net-script"
rem // determine the various path information we'll need to compile
rem // and run our script.
set _ScriptPath=%APPDATA%\js-net-script\%~nx1
set _ExePath=%_ScriptPath%.exe
set _LogPath=%_ExePath%.log
rem // copy the script to ensure it is on a local disk.
copy "%~f1" "%_ScriptPath%" >nul 2>&1
if errorlevel 1 set ERR=%errorlevel% && goto :ERROR
rem // compile the script. we use a debug build so that we can
rem // break into the debugger. we also log the build results to a
rem // log file, so that we can show them to the user if there is
rem // a problem.
%SYSTEMROOT%\Microsoft.NET\Framework\v1.1.4322\jsc.exe /out:"%_ExePath%" /target:exe /debug+ /fast- /nologo "%_ScriptPath%" > "%_LogPath%" 2>&1
if errorlevel 1 set ERR=%errorlevel% && goto :ERROR
rem // run the application, passing in arguments.
"%_ExePath%" %*
rem // delete the local copy of the script, and all build outputs.
del /s /q "%_ScriptPath%*" >nul 2>&1
goto :EOF
rem ///////////////////////////////////////////////////////////////////////
rem // INIT procedure
rem //
:INIT
rem @if not "%ECHO%"=="" echo %ECHO%
@if not "%OS%"=="Windows_NT" goto DOSEXIT
rem Set local scope and call MAIN procedure
setlocal & pushd & set RET=
set SCRIPTNAME=%~n0
set SCRIPTPATH=%~f0
if "%DEBUG%"=="1" (set TRACE=echo) else (set TRACE=rem)
if /i {%1}=={/help} (call :HELP %2) & (goto :HELPEXIT)
if /i {%1}=={/?} (call :HELP %2) & (goto :HELPEXIT)
:INIT_MAIN
set _SAVED_PROMPT=%PROMPT%
set PROMPT==$g
call :MAIN %*
set PROMPT=%_SAVED_PROMPT%
:HELPEXIT
popd & endlocal & set RET=%RET%
goto :EOF
rem ///////////////////////////////////////////////////////////////////////
rem // ERROR procedure
rem // ===============
rem //
rem // Abnormal exit. Expects the errorlevel has been stored in %ERR%.
rem //
:ERROR
if defined TRACE %TRACE% [ERROR! %0 %*]
echo.
echo WARNING: Script failed with errorlevel: %ERR%
echo.
echo Current directory is:
echo %CD%
echo Command-line was:
echo %CMDCMDLINE%
echo.
rem // show the build log. note: we'll show it in the console, but we
rem // could also popup notepad.exe
echo Compiler output:
echo.
type "%_LogPath%"
echo.
rem notepad "%_LogPath%"
rem // give the user a chance to see the results.
rem // note: this is not necessary if we open the log file in notepad.
rem // note: while paused here, you can copy the build outputs from
rem // the working directory in %APPDATA% to run ildasm, etc.
pause
rem // clean up all the build outputs.
del /s /q "%_ScriptPath%*" >nul 2>&1
goto :EOF
rem ///////////////////////////////////////////////////////////////////////
rem // DOSEXIT
rem // ====================================================================
rem //
rem // These must be the final lines in the script.
rem //
:DOSEXIT
echo This script requires Windows NT or later.
rem ///////////////////////////////////////////////////////////////////////