How do you loop a command from a list of strings to use RunSpaces in PowerShell.
Here is my code for a project I am working on.
It works with normal commands but I think it does not work with the following in [void]$PowerShell.AddScript
part. $singlefunction
is a string variable that contains command with switch parameter sometimes like CleanUp -All
:
iex -Command $singlefunction
Here is the code
# Loop for runspaces
foreach ($singlefunction in $listoffunctions)
{
$PowerShell = [PowerShell]::Create()
$PowerShell.RunspacePool = $RunspacePool
[void]$PowerShell.AddScript({
iex -Command $singlefunction
})
## start runspace asynchronously so that it does not block this loop
$handle = $PowerShell.BeginInvoke()
# Create job
$job = [pscustomobject]@{
PowerShell = $PowerShell
Handle = $handle
}
# Add first runspace to job list
$jobs.Add( $job )
}
The functions are added to the initial session state through:
ForEach($function in $scriptFunctions)
{
$Definition = $null
$Definition = Get-Content -Path Function:\$function -ErrorAction Continue
if( $Definition )
{
$SessionStateFunction = New-Object System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList $function , $Definition
$SessionState.Commands.Add( $SessionStateFunction )
}
}
Based on guessing, the cause of the issue is that you're not passing $singlefunction
as argument, to your runspace:
[void] $PowerShell.AddScript({
# `$singlefunction` does not exist in this context
Invoke-Expression -Command $singlefunction
})
If you want to pass that string as argument to Invoke-Expression
you can use .AddArgument
or .AddParameter
or .AddParameters
.
For instance:
[void] $PowerShell.AddScript({
Invoke-Expression -Command $args[0]
}).AddArgument($singlefunction)
However, if your intent is to execute the expression in that string this approach is just an over complication, .AddScript
takes a string that will be evaluated as a expression, solving the issue could be as simple as:
[void] $PowerShell.AddScript($singlefunction)
Demo:
using namespace System.Management.Automation.Runspaces
$cleanUpFunc = {
param([switch] $All, $Foo, $Bar)
"Called '$($MyInvocation.MyCommand.Name)' with parameters:",
$PSBoundParameters
}
$iss = [initialsessionstate]::CreateDefault2()
$iss.Commands.Add([SessionStateFunctionEntry]::new(
'CleanUp', $cleanUpFunc))
$singlefunction = 'CleanUp -All -Foo Hello -Bar World'
$rs = [runspacefactory]::CreateRunspace($iss)
$rs.Open()
$PowerShell = [PowerShell]::Create().
AddScript($singlefunction)
$PowerShell.Runspace = $rs
$PowerShell.Invoke()
# Outputs:
#
# Called 'CleanUp' with parameters:
#
# Key Value
# --- -----
# All True
# Foo Hello
# Bar World