我正在尝试创建一个执行脚本块的后台作业。我需要将此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大师都知道如何使这种语法有效吗?
提前致谢,
本
答案 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