Пользовательский модуль PowerShell и область действия для передачи на удаленные компьютеры

Я получаю смешанные результаты с наличием пользовательских функций в пользовательских модулях, на удаленных компьютерах, в зависимости от того, как я загружаю модуль. Деталь выглядит следующим образом:

Я написал специальный модуль, в котором есть отдельный файл функций. Структура выглядит следующим образом:

  • C: \ PowerShell-модули \ ModuleName
    • C: \ PowerShell-модули \ ModuleName.psd1
    • C: \ PowerShell-Modules \ MyFunction.ps1 (содержит функцию MyFunction).

Чтобы полагаться на автоматическую загрузку модуля, я изменяю $env:PSModulePath, чтобы он содержал "C:\PowerShell-Modules\".

В моем скрипте (например, PassRemote.ps1) "MyFunction" доступна и работает как положено. Однако при попытке запустить это на удаленном компьютере:

Invoke-Command -ComputerName $computername -UseSSL -ScriptBlock ${function:MyFunction} -ArgumentList $arg1

... происходит сбой, сообщая, что командлет / функция не распознан.

Единственный способ передать пользовательскую функцию - это явно загрузить модуль в сценарии. Чтобы было понятно, мне нужно написать строку:

Import-Module ModuleName 

внутри родительского скрипта (PassRemote.ps1). Только тогда функция может быть передана в удаленный сеанс.

Это проблема сферы?

1 ответ

Решение

Кажется, что явная загрузка модуля также загружает все содержимое функций / командлетов внутри него (то есть сам код). Таким образом, функции доступны для передачи во всей их полноте.

При автоматической загрузке модулей загружаются только имена доступных командлетов / функций (очевидно, в противном случае PS3+ потребовалось бы много времени для загрузки при запуске). Это означает, что, хотя сеанс PS "осведомлен" об автоматически загружаемых функциях, в этот момент он фактически не имеет кода для передачи в удаленный сеанс. К сожалению, использование "-ScriptBlock ${function:MyFunction}", похоже, не приводит к принудительному расширению или загрузке этой функции, чтобы она была доступна для прохождения.

Чтобы доказать приведенную выше теорию (и избежать явной загрузки модуля), мы можем запустить:

    $x = Get-Command MyFunction

а потом:

Invoke-Command -ComputerName $computername -UseSSL -ScriptBlock ${function:MyFunction} -ArgumentList $arg1

Было бы неплохо, если бы был какой-то способ сделать это в строке Invoke-Command, но я думаю, что именно поэтому я испытывал описанные выше сценарии.

Другие вопросы по тегам