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

时间:2012-08-07 10:54:05

标签: powershell

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

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

以下语法有效:

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大师都知道如何使这种语法有效吗?

提前致谢,

5 个答案:

答案 0 :(得分:13)

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

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

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

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

} | Wait-Job | Receive-Job

答案 1 :(得分:4)

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

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

产生以下输出:

System.String

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

答案 2 :(得分:4)

今天看起来很有效。

function LocalFunction
{
    param
    (
        [scriptblock] $block
    )

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

LocalFunction { "Hello"} 

答案 3 :(得分: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

答案 4 :(得分:0)

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

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

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

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

LocalFunction -ScriptBlock $sb