使用PowerShell的Invoke-Command进行远程处理时,如何包含本地定义的函数?

Dav*_*gue 29 powershell powershell-2.0 powershell-remoting

我觉得我错过了一些显而易见的东西,但我无法弄清楚如何做到这一点.

我有一个ps1脚本,其中定义了一个函数.它调用该函数,然后尝试远程使用它:

function foo
{
    Param([string]$x)

    Write-Output $x
}

foo "Hi!"

Invoke-Command -ScriptBlock { foo "Bye!" } -ComputerName someserver.example.com -Credential someuser@example.com
Run Code Online (Sandbox Code Playgroud)

这个简短的示例脚本打印出"嗨!" 然后崩溃说"术语'foo'不被识别为cmdlet,函数,脚本文件或可操作程序的名称."

我知道该功能未在远程服务器上定义,因为它不在ScriptBlock中.我可以在那里重新定义它,但我不愿意.我想定义一次该函数并在本地或远程使用它.有没有办法做到这一点?

alr*_*roc 34

你需要传递函数本身(而不是调用函数ScriptBlock).

就在上周我有同样的需求并且发现了这个SO讨论

所以你的代码将成为:

Invoke-Command -ScriptBlock ${function:foo} -argumentlist "Bye!" -ComputerName someserver.example.com -Credential someuser@example.com
Run Code Online (Sandbox Code Playgroud)

请注意,通过使用此方法,您只能在位置上将参数传递到函数中; 您无法在本地运行该函数时使用命名参数.


Jam*_*phy 27

您可以将函数的定义作为参数传递,然后通过创建脚本块然后对其进行点源来重新定义远程服务器上的函数:

$fooDef = "function foo { ${function:foo} }"

Invoke-Command -ArgumentList $fooDef -ComputerName someserver.example.com -ScriptBlock {
    Param( $fooDef )

    . ([ScriptBlock]::Create($fooDef))

    Write-Host "You can call the function as often as you like:"
    foo "Bye"
    foo "Adieu!"
}
Run Code Online (Sandbox Code Playgroud)

这样就不需要复制函数了.如果您愿意,也可以通过这种方式传递多个函数:

$allFunctionDefs = "function foo { ${function:foo} }; function bar { ${function:bar} }"
Run Code Online (Sandbox Code Playgroud)

  • 正是我想要的!您的解决方案与`$ Using:Var`结合使用可以达到目的:)非常感谢! (2认同)

Kei*_*ill 5

您还可以将函数和脚本放在文件(foo.ps1)中,然后使用FilePath参数将其传递给Invoke-Command:

Invoke-Command –ComputerName server –FilePath .\foo.ps1
Run Code Online (Sandbox Code Playgroud)

该文件将被复制到远程计算机并执行。