如何将对象传递给Get-Job子流程作为参考

问题描述

我需要编写一个Powershell脚本,该脚本从异步读取,然后将其写入System.IO.Ports.SerialPort对象。但是,在编写代码以使用Start-Job来简单地从对象中读取代码时,出现了错误。到目前为止,这是我的代码

$func = {
    function CheckPort 
    {
        param (
            [parameter(Mandatory=$true,ValueFromPipeline=$true)]
            [System.IO.Ports.SerialPort]$port
        )
            
        Write-Output $port.ReadLine()
    }
}

$port = new-Object System.IO.Ports.SerialPort COM4,9600,None,8,one
$port.open()

Start-Job -ScriptBlock {CheckPort $args[0]} -ArgumentList $port -Name “$computerName” -InitializationScript $func

运行上面的代码时,使用Receive-Object检查子流程的输出后,我看到一个错误。似乎不是$port对象按原样传递,而是先序列化然后未序列化:

Error: "Cannot convert the "System.IO.Ports.SerialPort" value of type "Deserialized.System.IO.Ports.SerialPort" to type "System.IO.Ports.SerialPort"."
    + CategoryInfo          : InvalidData: (:) [CheckPort],ParameterBindin...mationException
    + FullyQualifiedErrorId : ParameterargumentTransformationError,CheckPort
    + PSComputerName        : localhost

反正有使用Start-Job通过引用传递自变量吗? $port.ReadLine()正在阻塞,没有其他方法可以仅检查是否有要读取的内容,并且我有时需要写入端口,因此在这里肯定需要异步执行。

如果我尝试$using,也会遇到相同的错误

$port = new-Object System.IO.Ports.SerialPort COM4,one
$port.open()

Start-Job -ScriptBlock {
    $myPort = $using:port
    Write-Output $myPort.ReadLine()
}

解决方法

这两个方法不序列化对象。 foreach-object -parallel需要PS 7,但可以在PS 5中下载start-threadjob

Start-ThreadJob {
  $myPort = $using:port
  $myPort.ReadLine()
} | receive-job -wait -auto
foreach-object -parallel {
  $myPort = $using:port
  $myPort.ReadLine()
}