Bbb
Bbb

Reputation: 649

How to have multiple return values returned together within Powershell runspace threads?

How can I have the second $scriptBlock work as the first $scriptBlock does? The differences between the 2 are that the first one returns a single object from a command and the second one should return an array of objects from multiple commands?

To test this code you only need fill in the server names for $servers and an Exchange powershell hyperlink for $connectionUri and alternate between commenting out the first $scriptBlock (working) and the second $scriptBlock (not working).

Thanks

cls

Write-Host "Aynchronous";

# Create session state
$stopWatch = [System.Diagnostics.Stopwatch]::StartNew();

$myString = "this is session state!";
$sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault();
$sessionstate.Variables.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList "myString" ,$myString, "example string"));

# Create runspace pool consisting of $numThreads runspaces
$minimumAmountOfThreads = 1;
$maximumAmountOfThreads= 15;
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, 15, $sessionState, $Host);
$RunspacePool.Open();

$servers = @("server1","server2","server3");
$connectionUri = "http://[something]/powershell";

$threads = @();
$Jobs = @();
$asynchronousThreadCount = 0;
foreach ($server in $servers)
{
    $scriptBlock = "import-pssession (new-pssession -ConfigurationName Microsoft.Exchange -ConnectionUri $connectionUri) -AllowClobber; get-exchangeserver $server;"; # working
    #$scriptBlock = "import-pssession (new-pssession -ConfigurationName Microsoft.Exchange -ConnectionUri $connectionUri) -AllowClobber; $returnValue = @(); $returnValue += Get-MailboxDatabase -Server $server; return $returnValue;"; # NOT working
        #$scriptBlock = "import-module 'activedirectory'; Get-ADDomain"; # working
    #$scriptBlock = "import-module 'activedirectory'; $returnValue = @(); $returnValue += Get-ADDomain; return $returnValue;" # NOT working

    $asynchronousThreadCount ++;
    $runspaceObject = [PSCustomObject] @{
        Runspace = [PowerShell]::Create()
        Invoker = $null
    }
    $runspaceObject.Runspace.RunSpacePool = $runspacePool;
    $runspaceObject.Runspace.AddScript($scriptBlock) | Out-Null;
    $runspaceObject.Runspace.AddArgument($c) | Out-Null;
    $runspaceObject.Invoker = $runspaceObject.Runspace.BeginInvoke();
    $threads += $runspaceObject;
    $elapsed = $StopWatch.Elapsed;

    Write-Host "A synchronous created thread $asynchronousThreadCount " $elapsed;
}

Write-Host $threads.Count;
Write-Host "";
Write-Host "Waiting.." -NoNewline;
Do {
   Write-Host "." -NoNewline;
   Start-Sleep -Seconds 1;
} While ( $runspaceObject.Invoker.IsCompleted -contains $false ); 

$resultsAsynchronous = @();

foreach ($tr in $threads)
{
    $resultsAsynchronous += $tr.Runspace.EndInvoke($tr.Invoker);
    $tr.Runspace.Dispose();
}
$procCountMultiThread = $resultsAsynchronous.Count;

$runspacePool.Close();
$runspacePool.Dispose();

$elapsed = $StopWatch.Elapsed;
Write-Host "Multithread elapsed time: $elapsed";
Write-Host "Asynchronous return value count " $resultsAsynchronous.Count;
$resultsAsynchronous #| fl fqdn, AdminDisplayVersion;

Upvotes: 1

Views: 1127

Answers (1)

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174485

You need to escape $ when defining your scriptblocks using double-quotes:

$scriptBlock = "import-pssession (new-pssession -ConfigurationName Microsoft.Exchange -ConnectionUri $connectionUri) -AllowClobber; $returnValue = @(); $returnValue += Get-MailboxDatabase -Server $server; return $returnValue;"; # NOT working

ends up as the string

import-pssession (new-pssession -ConfigurationName Microsoft.Exchange -ConnectionUri ) -AllowClobber;  = @();  += Get-MailboxDatabase -Server ; return ;

Escape the relevant variable sigils with `:

$scriptBlock = "import-pssession (new-pssession -ConfigurationName Microsoft.Exchange -ConnectionUri $connectionUri) -AllowClobber; `$returnValue = @(); `$returnValue += Get-MailboxDatabase -Server $server; return `$returnValue;"; 

Upvotes: 2

Related Questions