Sharing variables between jobs

2.5k views Asked by At

I have a powershell script which is supposed to run a background job until the user decides it should end. The background job is this Script Block:

$block = 
    {
         param(
            [Parameter(Mandatory = $true, Position = 0, valueFromPipeline = $true)]
            $Counters,
            [Parameter(Mandatory = $true, Position = 1, valueFromPipeline = $false)]
            [ref]$killSwitch,
            [Parameter(Mandatory = $false, Position = 2, valueFromPipeline = $false)]
            [long]$SampleInterval = 1000
         )
        [System.Diagnostics.Stopwatch]$sw = New-Object System.Diagnostics.StopWatch
        $sw.Start()
        $last = 0
        $report = New-Object PSObject
        $report | Add-Member -MemberType NoteProperty -Name Start -Value ([DateTime]::Now)
        while(!$killSwitch)
        {
            if($sw.ElapsedMilliseconds -gt $last + $SampleInterval)
            {
                $rec = Get-CounterSample -counters $Counters
                $report | Add-Member -MemberType NoteProperty -Name $sw.ElapsedMilliseconds -Value $rec
                $last = $sw.ElapsedMilliseconds
            }
        }
        $report | Add-Member -MemberType NoteProperty -Name End -Value ([DateTime]::Now)
        return $report  
    }

As you can see, I'm trying to pass in a boolean ($killSwitch) as a way of stopping the While loop once the user/ caller is done. I call it in the following way:

[bool]$kill = $false
$job = Start-Job -Name twProcMon -ScriptBlock $block -ArgumentList $Counters, ([ref]$kill), $SampleInterval
Read-Host
$kill = $true
Wait-Job $job
Receive-Job $job

I get an error:

Cannot process argument transformation on parameter 'killSwitch'. Reference type is expected in argument.

How do I pass a bool by reference to a code block, such that I can kill the while loop from outside the job? Is it possible?

1

There are 1 answers

0
Ansgar Wiechers On BEST ANSWER

You can't pass variables from one job to another. What you can do is have the jobs create a specific file on completion, and monitor for the existence of that file while they're running. Make the content of the script block so that the operation terminates without creating the marker file when the file is discovered.

$block = {
  $marker = 'C:\path\to\marker.txt'
  do while (-not ((Test-Path -LiteralPath $marker) -or ($completionCondition))) {
    # ...
    # do stuff here
    # ...
    if ($completionCondition) { $null > $marker }
  }
}