1

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?

Orphid
  • 2,722
  • 2
  • 27
  • 41
  • I spent close to 10 hours looking for a way. But the jobs are isolated so unaware of global variables, or referenced variables. Tricks to pass between functions in same shell don't fly between jobs unless doing a file. It could be xml or csv for more information than a string. I thought. Look at https://stackoverflow.com/questions/8415603/automatically-pulling-data-from-a-powershell-job-while-running – Kirt Carson Sep 01 '19 at 19:42

1 Answers1

2

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 }
  }
}
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328