我如何包括本地定义的函数使用PowerShell的调用命令远程处理时?我如何包括本地定义的函数使用P

2019-06-14 17:00发布

我觉得我失去了一些东西,应该是显而易见的,但我只是无法弄清楚如何做到这一点。

我有一个在其定义的功能的PS1脚本。 它调用的函数,然后尝试远程使用它:

function foo
{
    Param([string]$x)

    Write-Output $x
}

foo "Hi!"

Invoke-Command -ScriptBlock { foo "Bye!" } -ComputerName someserver.example.com -Credential someuser@example.com

这个简短的示例脚本打印“嗨!” 然后崩溃说“术语‘富’不被识别为cmdlet,函数,脚本文件或可操作的程序的名称。”

据我所知,该功能不是在远程服务器上定义的,因为它不是在脚本块。 我可以有重新定义它,但我宁愿不要。 我想一次定义的功能和使用本地或远程。 有没有做到这一点的好办法?

Answer 1:

你需要传递函数本身(而不是在该函数的调用ScriptBlock )。

我有同样的需求就在上周,发现该SO讨论

所以,你的代码将变为:

Invoke-Command -ScriptBlock ${function:foo} -argumentlist "Bye!" -ComputerName someserver.example.com -Credential someuser@example.com

注意,通过使用这种方法,你只能传递参数给你的函数位置上; 当你在本地运行的功能,你什么时候不能使用命名参数。



Answer 2:

你也可以传递函数作为参数的定义,然后通过创建一个脚本块重新定义远程服务器上的功能,然后点采购它:

$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!"
}

这消除了需要有你的函数的副本。 您也可以通过这种方式不止一种功能,如果你是这样的倾向:

$allFunctionDefs = "function foo { ${function:foo} }; function bar { ${function:bar} }"


Answer 3:

You can also put the function(s) as well as the script in a file (foo.ps1) and pass that to Invoke-Command using the FilePath parameter:

Invoke-Command –ComputerName server –FilePath .\foo.ps1

The file will be copied to the remote computers and executed.



Answer 4:

尽管这是一个老问题,我想补充我的解决方案。

有趣的足够功能测试中的脚本块的PARAM列表中,没有考虑类型[脚本块]的参数,并为此需要转换。

Function Write-Log 
{
    param(
        [string]$Message
    )

    Write-Host -ForegroundColor Yellow "$($env:computername): $Message"
}

Function Test
{
    $sb = {
        param(
            [String]$FunctionCall
        )

        [Scriptblock]$WriteLog = [Scriptblock]::Create($FunctionCall) 
        $WriteLog.Invoke("There goes my message...")               
    }

    # Get function stack and convert to type scriptblock 
    [scriptblock]$writelog = (Get-Item "Function:Write-Log").ScriptBlock 

    # Invoke command and pass function in scriptblock form as argument 
    Invoke-Command -ComputerName SomeHost -ScriptBlock $sb -ArgumentList $writelog
}

Test

另一个posibility是传递一个哈希表包含所有你想在远程会话中有可用的方法我们的脚本块:

Function Build-FunctionStack 
{
    param([ref]$dict, [string]$FunctionName)

    ($dict.Value).Add((Get-Item "Function:${FunctionName}").Name, (Get-Item "Function:${FunctionName}").Scriptblock)
}

Function MyFunctionA 
{
    param([string]$SomeValue)

    Write-Host $SomeValue
}

Function MyFunctionB
{
    param([int]$Foo)

    Write-Host $Foo
}

$functionStack = @{}

Build-FunctionStack -dict ([ref]$functionStack) -FunctionName "MyFunctionA"
Build-FunctionStack -dict ([ref]$functionStack) -FunctionName "MyFunctionB" 

Function ExecuteSomethingRemote
{
    $sb = {
        param([Hashtable]$FunctionStack)

        ([Scriptblock]::Create($functionStack["MyFunctionA"])).Invoke("Here goes my message");
        ([Scriptblock]::Create($functionStack["MyFunctionB"])).Invoke(1234);

    }

    Invoke-Command -ComputerName SomeHost -ScriptBlock $sb -ArgumentList $functionStack
}

ExecuteSomethingRemote


文章来源: How do I include a locally defined function when using PowerShell's Invoke-Command for remoting?