source

PowerShell의 Invoke-Command를 원격으로 사용할 때 로컬로 정의된 기능을 포함하려면 어떻게 해야 합니까?

factcode 2023. 9. 21. 21:34
반응형

PowerShell의 Invoke-Command를 원격으로 사용할 때 로컬로 정의된 기능을 포함하려면 어떻게 해야 합니까?

분명해야 할 무언가를 놓치고 있는 것 같지만, 어떻게 해야 할지 모르겠어요.

저는 ps1 스크립트에 함수가 정의되어 있습니다.함수를 호출한 다음 원격으로 사용을 시도합니다.

function foo
{
    Param([string]$x)

    Write-Output $x
}

foo "Hi!"

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

이 짧은 예제 스크립트는 "Hi!"를 인쇄한 다음 "'foo'라는 용어는 cmdlet, 함수, 스크립트 파일 또는 작동 가능한 프로그램의 이름으로 인식되지 않습니다"라고 말하며 충돌합니다.

Script Block에 없기 때문에 원격 서버에 함수가 정의되어 있지 않은 것으로 알고 있습니다.거기서 다시 정의를 내릴 수는 있겠지만, 그러지 않는 게 낫겠어요.기능을 한번 정의하고 로컬 또는 원격으로 사용하고 싶습니다.이것을 할 수 있는 좋은 방법이 있습니까?

함수 자체를 전달해야 합니다(의 함수에 대한 호출이 아님).ScriptBlock).

저는 지난주에도 같은 요구를 가지고 있었고 이 SO에 대한 논의를 찾았습니다.

코드는 다음과 같습니다.

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

이 메서드를 사용하면 함수를 위치적으로만 전달할 수 있으며 함수를 로컬로 실행할 때처럼 명명된 매개 변수를 사용할 수 없습니다.

함수의 정의를 매개 변수로 전달한 다음 스크립트 블록을 만든 다음 점 소싱하여 원격 서버에서 함수를 다시 정의할 수 있습니다.

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

함수와 스크립트를 파일(foo.ps1)에 넣고 FilePath 매개 변수를 사용하여 Invoke-Command에 전달할 수도 있습니다.

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

파일이 원격 컴퓨터에 복사되어 실행됩니다.

비록 오래된 질문이지만 제 해결책을 추가하고 싶습니다.

재미있게도 함수 테스트 내 스크립트 블록의 매개 변수 목록은 [scriptblock] 유형의 인수를 사용하지 않으므로 변환이 필요합니다.

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

원격 세션에서 사용할 수 있는 모든 메서드를 포함하는 스크립트 블록에 해시 테이블을 전달하는 것도 가능합니다.

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

언급URL : https://stackoverflow.com/questions/11367367/how-do-i-include-a-locally-defined-function-when-using-powershells-invoke-comma

반응형