简体   繁体   English

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

[英]How do I pass a scriptblock as one of the parameters in start-job

I'm trying to create a background job, which executes a scriptblock. 我正在尝试创建一个执行脚本块的后台作业。 I need to pass this scriptblock in as a parameter, but I can't seem to get the syntax to work. 我需要将此scriptblock作为参数传递,但我似乎无法使语法工作。 The scriptblock is being converted to a string somewhere along the way. 脚本块正在转换为沿途的某个字符串。

It works fine when I pass the script block to a local function, but not through start-job 当我将脚本块传递给本地函数时,它工作正常,但不是通过启动作业

The following syntax works: 以下语法有效:

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

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

LocalFunction -ScriptBlock { echo "hello" }

This outputs "got hello" as expected. 这按预期输出“得到你好”。

But the following fails: 但是以下失败了:

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

The error it returns is 它返回的错误是

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

So if I'm reading the error right, it appears that -argumentlist is somehow forcing its arguments into strings. 因此,如果我正确地读错误,那么似乎-argumentlist会以某种方式将其参数强制转换为字符串。

Any powershell gurus know how to make this syntax work? 任何powershell专家知道如何使这种语法工作?

Thanks in advance, 提前致谢,

Ben

Here's one way to solve this, pass the scriptblock code as a string, then create a scriptblock from the string inside the job and execute it 这是解决此问题的一种方法,将scriptblock代码作为字符串传递,然后从作业内的字符串创建一个scriptblock并执行它

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

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

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

} | Wait-Job | Receive-Job

Based on my experiments, PowerShell is parsing -ArgumentList, which is an Object[], as a string, even when you pass in a script block. 根据我的实验,即使传入脚本块,PowerShell也会将-ArgumentList(它是一个Object [])解析为字符串。 The following code: 以下代码:

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

results in the following output: 得到以下输出:

System.String System.String

As far as I know, the only solution here is Shay's, though you don't need to pass in the -ArgumentList as a string as PowerShell will parse your script block as a string in this case. 据我所知,这里唯一的解决方案是Shay,尽管你不需要将-ArgumentList作为字符串传递,因为PowerShell会在这种情况下将脚本块解析为字符串。

Looks like this works today. 看起来今天有效。

function LocalFunction
{
    param
    (
        [scriptblock] $block
    )

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

LocalFunction { "Hello"} 

You have to read it in as a string and then convert it to a scriptblock. 您必须以字符串形式阅读它,然后将其转换为scriptblock。

In powershell v1 you can do this: 在powershell v1中,您可以这样做:

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

And in powershell v2 you can do this: 在powershell v2中你可以这样做:

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

So your code would look like this: 所以你的代码看起来像这样:

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

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

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

LocalFunction -ScriptBlock "echo 'hello'"

The '[scriptblock]::Create($ScriptBlock)' will place the curly braces around the string for you creating the script block. '[scriptblock] :: Create($ ScriptBlock)'会在字符串周围放置花括号,以便您创建脚本块。

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

So if your desire is to insert an inline scriptblock, then Shay's solution (as noted) is probably the best. 因此,如果您希望插入内联脚本块,那么Shay的解决方案(如上所述)可能是最好的。 On the other hand if you simply want to pass a scriptblock as a parameter consider using a variable of type scriptblock and then passing that as the value of the -ScriptBlock parameter. 另一方面,如果您只想传递一个scriptblock作为参数,请考虑使用scriptblock类型的变量,然后将其作为-ScriptBlock参数的值传递。

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

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

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

LocalFunction -ScriptBlock $sb

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM