Search code examples
multithreadingpowershellrunspacepowershell-modulepowershell-sdk

Call function from module inside a runspace


I have some functions in a module I would like to call from a runspace but It´s not working. I assume that I somehow have to send the module to the runspace.

The example below works fine.

$hash = [hashtable]::Synchronized(@{})
$hash.OutData
$runspace = [runspacefactory]::CreateRunspace()
$runspace.Open()
$runspace.SessionStateProxy.SetVariable('Hash',$hash)
$powershell = [powershell]::Create()
$powershell.Runspace = $runspace

$powershell.AddScript({

    $hash.OutData = Get-Date

}) | Out-Null

$handle = $powershell.BeginInvoke()
While (-Not $handle.IsCompleted) {
    Start-Sleep -Milliseconds 100
}

$powershell.EndInvoke($handle)
$runspace.Close()
$powershell.Dispose()

But if I call my own function instead like this, the OutData is blank. The function works fine outside of the runspace.

$powershell.AddScript({

    $hash.OutData = Get-customData

}) | Out-Null

What do I have to do be able to call my function?


Solution

  • If your module isn't in one of the directories listed in $env:PSModulePath (or the latter environment variable isn't defined, which could happen on Unix if you're hosting the PowerShell SDK in an external executable), you must import it explicitly:

    $yourFullModulePath = '<your-full-module-path-here>'
    
    # Create a default session state and import a module into it.
    $iss = [InitialSessionState]::CreateDefault()
    $iss.ImportPSModule($yourFullModulePath)
    
    # Create the runspace with the initial session state and open it.
    $runspace = [runspacefactory]::CreateRunspace($iss)
    $runspace.Open()
    
    # Create a PowerShell instance and assign the runspace to it.
    $powershell = [powershell]::Create($runspace)
    
    # ...
    

    Note that you can simplify your code by taking advantage of the fact that a [powershell] instance automatically creates a runspace:

    # Pass the initial session state directly to [powershell]::Create(),
    # which automatically provides a runspace.
    $powershell = [powershell]::Create($iss)
    
    # Access the [powershell] instance's runspace via the `.Runspace` property.
    $powerShell.Runspace.SessionStateProxy.SetVariable('Hash', $hash)
    
    # ...