Как включить локально определенную функцию при использовании PowerShell Invoke-Command для удаленного доступа?
Я чувствую, что мне не хватает чего-то, что должно быть очевидно, но я просто не могу понять, как это сделать.
У меня есть ps1 script, у которого есть определенная в нем функция. Он вызывает функцию, а затем пытается использовать ее удаленно:
function foo
{
Param([string]$x)
Write-Output $x
}
foo "Hi!"
Invoke-Command -ScriptBlock { foo "Bye!" } -ComputerName someserver.example.com -Credential [email protected]
Этот короткий пример script печатает "Привет!" а затем выдается сообщение: "Термин" foo "не распознается как имя командлета, функции, файла script или исполняемой программы".
Я понимаю, что функция не определена на удаленном сервере, потому что она не находится в ScriptBlock. Я мог бы переопределить его там, но я бы предпочел. Я хотел бы определить функцию один раз и использовать ее либо локально, либо удаленно. Есть ли хороший способ сделать это?
Ответы
Ответ 1
Вам нужно передать функцию (не вызов функции в ScriptBlock
).
У меня была такая же потребность только на прошлой неделе и нашла эту SO-дискуссию
Итак, ваш код станет:
Invoke-Command -ScriptBlock ${function:foo} -argumentlist "Bye!" -ComputerName someserver.example.com -Credential [email protected]
Обратите внимание, что с помощью этого метода вы можете только передавать параметры в свою функцию по позициям; вы не можете использовать именованные параметры, как вы могли бы при запуске функции локально.
Ответ 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} }"
Ответ 3
Вы также можете поместить функции (-ы), а также script в файл (foo.ps1) и передать это команде Invoke-Command с помощью параметра FilePath:
Invoke-Command –ComputerName server –FilePath .\foo.ps1
Файл будет скопирован на удаленные компьютеры и выполнен.