Search code examples
powershellscriptingjobs

Can I pass a function and call it in a PSJobs scriptblock, and receive a return value?


When I run get-job | receive-job -keep I get no results and have no way to verify that my function is passed and working. Can I pass a function like this into a psjob? How do I capture the return value afterwards?

$servers = @("xxxx", "xxxx")
$jobs = New-Object System.Collections.ArrayList;
foreach ($server in $servers)
{
    $jobName = $server + "_job";
    $scriptBlock = 
    {
    
        param($server)
        param($portNumber)
        
        Function testPort ($server, $portNumber)
        {
            $testPort = New-Object System.Net.Sockets.TCPClient # -ArgumentList $server, 3389;
            $testPort.SendTimeout = 3;
            try
            {
                $testPort.Connect($server, 3389);
            }
            catch
            {
                #do nothing;
            }
            $result = $testPort.Connected;
            $testPort.Close();
                    
            return $result;
        }
    
        testPort -server $server -portNumber 3389; sleep 10;    
    }
    $portNumber = "3389";
    
    #Start-Job -Name $jobName -ScriptBlock {$scriptBlock} -ArgumentList $server, $portNumber;

    $jobs.Add((Start-Job -Name $jobName -ScriptBlock {$scriptBlock} -ArgumentList $server, $portNumber | Out-Null));

}

$jobsReturnValues = New-Object System.Collections.ArrayList;
foreach ($job in $jobs)
{
    $jobsReturnValues.Add(($job | Wait-Job | Receive-Job | Out-Null));
}

Solution

  • The code is almost fine, you did not have many errors. The main issue was the use of Out-Null, the { } on -ScriptBlock {$scriptBlock} and the param( ) block was defined 2 times in your function. I did a little modification to your function too :)

    $servers = @('google.com','twitter.com')
    $jobs = New-Object System.Collections.ArrayList;
    $testPort = 80
    
    foreach ($server in $servers)
    {
        $jobName = $server + "_job";
        $scriptBlock = {
            param(
                [string]$server,
                [int]$portNumber
            )
            
            Function testPort ($server, $portNumber)
            {
                $testPort = New-Object System.Net.Sockets.TCPClient # -ArgumentList $server, 3389;
                $testPort.SendTimeout = 3;
                try
                {
                    $testPort.Connect($server, $portNumber);
                }
                catch
                {
                    #do nothing;
                }
                
                $result = $testPort.Connected;
                $testPort.Close();
                        
                [pscustomobject]@{
                    ServerName = $server
                    Port = $portNumber
                    TestConnection = $result
                }
            }
    
            testPort -server $server -portNumber $portNumber
        }
    
        $jobs.Add((Start-Job -Name $jobName -ScriptBlock $scriptBlock -ArgumentList $server, $testPort)) > $null;
    
    }
    
    $jobsReturnValues = New-Object System.Collections.ArrayList;
    foreach ($job in $jobs)
    {
        $jobsReturnValues.Add(($job | Receive-Job -Wait -AutoRemoveJob)) > $null;
    }
    

    Looks like this:

    PS C:\> $jobsReturnValues|select * -ExcludeProperty RunspaceID|ft
    
    ServerName  Port TestConnection
    ----------  ---- --------------
    google.com    80           True
    twitter.com   80           True