It is possible to configure F# script files so that they may be invoked directly without directly specifying the script runner application and their file extension, and made accessible through the command PATH environment variable.
The steps to do so are as follows:
- Set the particular script engine as the default "open with" program for the script file type extension using Windows Explorer
- Appended the script extension to the PathExt environment variable, which will classify it as executable
- Optionally, include the directory path containing the scripts to Windows Path environment variable
My question: how to get arguments through to the script when you are not directly invoking it's runner application with it.
The following provides a simple technique for configuring your windows system to include F# as a scripting language on par with cmd and batch files. Consequently, the scripts are accessible from the environment path, invocable without a file type extension, and may be passed any number of arguments. This technique should be applicable to other scripting languages such as powershell, python, etc.
The following is a batch file for establishing this configuration for F# 3.1 in .Net 4.0:
configure.bat
rem absolute filename of the F# script runner, Fsi.exe
set fsharpScriptRunner="C:\Program Files (x86)\Microsoft SDKs\F#\3.1\Framework\v4.0\Fsi.exe"
rem script runner command for fsi.exe to execute script and exit without advertising itself
set fsharpScriptRunnerCmd=%fsharpScriptRunner% --nologo --exec
rem associate "FSharpScript" files with fsharpScriptRunnerCmd, appending
rem the file name and remaining line arguments into the commandline
rem after the delimiter "--"
ftype FSharpScript=%fsharpScriptRunnerCmd% %%1 "--" %%*
rem associate file extension ".fsx" with the file type "FSharpScript"
assoc .fsx=FSharpScript
rem add ".fsx" to the list of file types treated as executable
set pathext=%pathext%;.fsx
Note, the presence of "--" in the "ftype" command line serves as a delimiter to assist the script in distinguish it's command line arguments from those of the script runner; an F# script receives all the arguments and must parse out it's arguments. My clumsy F# version of this parsing using the provided delimiter is as follows:
open System
let args =
Environment.GetCommandLineArgs()
|> Seq.skipWhile (fun p -> p <> "--")
|> Seq.skip 1
|> List.ofSeq
Enjoy.