My Technical Notes

Wednesday, 11 June 2014

Embedding F# in PowerShell ("hacky" way)

Following on from Doug Finke's ‘Embedding’ F# in PowerShell article, I wanted to load F# scripts within PowerShell. I took his code and modularized it to have two functions:

  • Import-FSharpScript - Import an F# script via its file path.
  • Import-FSharpCode - Import F# code which is in a string.

Here is the module (ImportFSharp-Module.psm1):


Function Import-FSharpScript([string]$scriptPath) {
    $fscExe = 'C:\Program Files (x86)\Microsoft F#\v4.0\Fsc.exe'
    
    if (-not (Test-Path $fscExe) ) {
        Write-Host 'Change the $fscExe variable'
    } else  {
    
        $dllFileName = "file.dll"
        
        # -a to build a library and -o to specify the output file program
        & $fscExe $scriptPath -a -o $dllFileName

        $dllFileBytes = [System.IO.File]::ReadAllBytes( (Resolve-Path $dllFileName ) )

        Remove-Item $dllFileName
        
        [void][Reflection.Assembly]::Load( $dllFileBytes )
    }
}

Function Import-FSharpCode([string]$scriptString) {
    $scriptFileName = [IO.Path]::GetTempFileName()
    Set-Content $scriptFileName $scriptString
    Import-FSharpScript $scriptFileName
    Remove-Item $scriptFileName
}

Export-ModuleMember -Function 'Import-FSharpCode'
Export-ModuleMember -Function 'Import-FSharpScript'
Which is imported as:

Import-Module 'C:\Path\to\ImportFSharp-Module.psm1'
In the example given on Doug's page, if we had a literal F# string embedded within our code we could import:

$fibCode = @"
#light
module Strangelights.Fibonacci
let fibs =
    (1,1) |> Seq.unfold
        (fun (n0,n1) ->
            Some(n0, (n1, n0 + n1)))
let get n =
    Seq.nth n fibs
"@

Import-FSharpCode $fibCode
On the other hand, if all this Fibonacci code was in a file called fib.fs, we could import the file:

Import-FSharpScript 'C:\Path\to\fib.fs'
Lastly, it is worth mentioning that there is an official way of doing this, but I couldn't get it to work. See Add-Type.

No comments: