如何将脚本块作为start-job中的参数之一传递

ben*_*ben 16 powershell

我正在尝试创建一个执行脚本块的后台作业.我需要将此scriptblock作为参数传递,但我似乎无法使语法工作.脚本块正在转换为沿途的某个字符串.

当我将脚本块传递给本地函数时,它工作正常,但不是通过启动作业

以下语法有效:

function LocalFunction
{
    param (
        [parameter(Mandatory=$true)]
        [ScriptBlock]$ScriptBlock
    )

    &$ScriptBlock | % { echo "got $_" }
}

LocalFunction -ScriptBlock { echo "hello" }
Run Code Online (Sandbox Code Playgroud)

这按预期输出"得到你好".

但是以下失败了:

$job = start-job -argumentlist { echo "hello" } -scriptblock {
    param (
        [parameter(Mandatory=$true)]
        [ScriptBlock]$ScriptBlock
    )
    &$ScriptBlock | % { echo "got $_" }
}
start-sleep -s 1
receive-job $job
Run Code Online (Sandbox Code Playgroud)

它返回的错误是

Receive-Job : Cannot process argument transformation on parameter 'ScriptBlock'. Cannot convert the " echo "hello" " value of type "System.String" to type "System.Management.Automation.ScriptBlock".
Run Code Online (Sandbox Code Playgroud)

因此,如果我正确地读错误,那么似乎-argumentlist会以某种方式将其参数强制转换为字符串.

任何powershell专家知道如何使这种语法工作?

提前致谢,

Sha*_*evy 15

这是解决此问题的一种方法,将scriptblock代码作为字符串传递,然后从作业内的字符串创建一个scriptblock并执行它

Start-Job -ArgumentList "write-host hello"  -scriptblock {

    param (
        [parameter(Mandatory=$true)][string]$ScriptBlock
    )

    & ([scriptblock]::Create($ScriptBlock))

} | Wait-Job | Receive-Job
Run Code Online (Sandbox Code Playgroud)

  • 这不回答如何传递脚本块的问题,我也需要这样做. (2认同)
  • 不,你是对的,它没有直接回答问题,但它提供了一种解决方法.据我所知,参数是序列化的(就像在远程处理中一样),而scriptblocks只作为字符串.解决方法是使用ScriptBlock.Create方法. (2认同)
  • 只是为了澄清,PowerShell 序列化了 Job 和 Remoting cmdlet 的参数。 (2认同)

awr*_*t18 6

看来今天这个办法有效。

function LocalFunction
{
    param
    (
        [scriptblock] $block
    )

    $block.Invoke() | % { "got $_" }
}

LocalFunction { "Hello"} 
Run Code Online (Sandbox Code Playgroud)