在带有参数的函数上使用Invoke-Command -ScriptBlock

30

我正在编写一段PowerShell脚本,将使用Invoke-Command及其-ScriptBlock参数在远程主机上执行命令。例如:

function Foo {
    ...
    return "foo"
}
$rv = Invoke-Command --Credential $c --ComputerName $fqdn -ScriptBlock ${function:Foo}

这个工作得很好。现在我想做的是同样的事情,但是用本地参数调用一个函数。例如:

function Bar {
    param( [String] $a, [Int] $b )
    ...
    return "foo"
}
[String] $x = "abc"
[Int] $y = 123
$rv = Invoke-Command --Credential $c --ComputerName $fqdn -ScriptBlock ${function:Foo($x,$y)}

但这并不起作用:

Invoke-Command:无法验证参数“ScriptBlock”上的参数。该参数为空。提供非空参数,然后再试一次。

我应该如何使用带有参数的本地函数作为-ScriptBlock的Invoke-Command?

我知道可以将整个函数和参数都包装在一个大代码块中,但在我看来,这不是一个干净的方法。

4个回答

51

我认为你想要的是:

function Foo ( $a,$b) {
    $a
    $b
    return "foo"
}

$x = "abc"
$y= 123

Invoke-Command -Credential $c -ComputerName $fqdn -ScriptBlock ${function:Foo} -ArgumentList $x,$y

谢谢,太棒了!我一直在尝试使用param() + -Arguments的组合,但都没有成功。 - Christopher Neylan
找到这个解决方案花了我好几个小时;-) 比导出/导入会话好多了 谢谢! - icnivad
1
我认为正确的格式应该是 -ScriptBlock {$function:Foo}(注意 $ 的位置)。 - Mourndark
2
{$function:Foo}${function:Foo}之间有很大的区别。前者中的花括号表示脚本块,因此该表达式的含义为:“在函数作用域中解析为变量foo的脚本块。” 后者中的花括号表示变量名被按字面意思解释,因此它简单地翻译为:“函数范围内的变量foo。” 如果“foo”变量的名称带有空格或其他特殊字符,则这将非常有用。 - nohwnd
我曾希望这个技巧也适用于runspace scriptblocks。但它没有奏效。不过尝试一下也是值得的。 - MKANET
显示剩余4条评论

9

您可以将函数包装在块中并传递该块;

$a = {
  function foo{}
  foo($args)
}

$a.invoke() // Locally

$rv = Invoke-Command --Credential $c --ComputerName $fqdn -ScriptBlock $a //remotely

不过它并不十分优雅。


2

这也可以工作:

function foo
{
    param([string]$hosts, [string]$commands)
    $scriptblock = $executioncontext.invokecommand.NewScriptBlock($commands)
    $hosts.split(",") |% { Invoke-Command -Credential $cred -ComputerName $_.trim() -Scriptblock $scriptblock }
}

0
$Log = "PowerShellCore/Operational"

Invoke-Command -ComputerName Server01 -ScriptBlock {Get-WinEvent -LogName $Using:Log -MaxEvents 10}\

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接