20

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

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

以下语法有效:

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

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

LocalFunction -ScriptBlock { echo "hello" }

这会按预期输出“打招呼”。

但以下失败:

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

它返回的错误是

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".

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

任何 powershell 大师都知道如何使这种语法起作用吗?

提前致谢,

4

5 回答 5

20

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

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

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

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

} | Wait-Job | Receive-Job
于 2012-08-07T11:29:24.290 回答
5

看起来这在今天有效。

function LocalFunction
{
    param
    (
        [scriptblock] $block
    )

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

LocalFunction { "Hello"} 
于 2015-02-07T13:07:06.663 回答
4

根据我的实验,即使您传入脚本块,PowerShell 也会将 -ArgumentList(它是一个 Object[])解析为字符串。以下代码:

$job = start-job -scriptblock { $args[0].GetType().FullName } -argumentlist { echo "hello" }
start-sleep -s 1
receive-job $job

产生以下输出:

系统字符串

据我所知,这里唯一的解决方案是 Shay's,尽管您不需要将 -ArgumentList 作为字符串传递,因为在这种情况下,PowerShell 会将您的脚本块解析为字符串。

于 2012-09-03T18:12:13.230 回答
1

您必须将其作为字符串读入,然后将其转换为脚本块。

在 powershell v1 中,您可以这样做:

$ScriptBlock = $executioncontext.invokecommand.NewScriptBlock($string)

在 powershell v2 中,您可以这样做:

$ScriptBlock = [scriptblock]::Create($string)

所以你的代码看起来像这样:

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

    $sb = [scriptblock]::Create($ScriptBlock)

    $sb | % { echo "got $_" }
}

LocalFunction -ScriptBlock "echo 'hello'"

'[scriptblock]::Create($ScriptBlock)' 将在字符串周围放置花括号,以便您创建脚本块。

在这里找到信息http://get-powershell.com/post/2008/12/15/ConvertTo-ScriptBlock.aspx

于 2013-03-26T19:08:18.740 回答
1

因此,如果您希望插入内联脚本块,那么 Shay 的解决方案(如前所述)可能是最好的。另一方面,如果您只是想将脚本块作为参数传递,请考虑使用类型变量,scriptblock然后将其作为-ScriptBlock参数的值传递。

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

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

[scriptblock]$sb = { echo "hello" }

LocalFunction -ScriptBlock $sb
于 2016-04-14T16:04:32.093 回答