Модули PowerShell

Простейший пример

Рассмотрим простейший сетап, в котором используется модуль.

Он состоит из главного скрипта main.ps1 который импортирует дополнительные функции из модуля mod.psm1

Модуль должен иметь расширение psm1 и находится в директории с таким же названием как и psm1 файл.

modules/ ├── main.ps1 └── mod └── mod.psm1

# mod.psm1 function Show-Url { param([string] $name) Write-Output "https://www.$name.ru" }

# main.ps1 Import-Module "$PSScriptRoot\mod" Show-Url "heihei"

.\main.ps1

https://www.aredel.com

Get-Module

Изучить данные о модуле можно командой Get-Module

Get-Module mod

ModuleType Version PreRelease Name ExportedCommands ---------- ------- ---------- ---- ---------------- Script 0.0 mod Show-Url

В дальнейшем мы будем часто обращаться к ExportedCommands, так что отметим наличие там единственной функции Show-Url

Remove-Module

Добавим в модуль ещё одну функцию

function Show-Url { param([string] $name) Write-Output "https://www.$name.ru" } function Show-Hoster { Write-Output "https://www.beget.com" }


Get-Module не увидит это изменение. Модуль уже был сохранен в кэш и ни разу не перезаписывался с тех пор.

Get-Module mod

ModuleType Version PreRelease Name ExportedCommands ---------- ------- ---------- ---- ---------------- Script 0.0 mod Show-Url

Удалим модуль из кэша вручную

Remove-Module mod Get-Module mod

Импортируем модуль вручную

Import-Module mod Get-Module mod

ModuleType Version PreRelease Name ExportedCommands ---------- ------- ---------- ---- ---------------- Script 0.0 mod {Show-Hoster, Show-Url}

Теперь, после ручной перезагрузки модуля, Get-Module показывает обе функции.

Удалим вторую функцию и заново перезагрузим модуль.

-Force

Изменим код нашего модуля. Уберём www. и вместо https оставим http

# mod.psm1 function Show-Url { param([string] $name) Write-Output "http://$name.ru" }

После вызова main.ps1 ничего не изменилось.

.\main.ps1

https://www.heihei.website

Модуль сохранён в кэш, поэтому для применения изменений нужно его оттуда удалить с помощью Remove-Module

Remove-Module mod
.\main.ps1

http://www.heihei.website

Вернём mod.psm1 в исходное состояние а в main.ps1 используем опцию -Force при загрузке модуля.

# main.ps1 Import-Module "$PSScriptRoot\mod" -Force Show-Url "heihei"

.\main.ps1

https://www.heihei.website

В этом случае удалять модуль из кэша вручную не потребовалось.

Export-ModuleMember

Добавим в модуль ещё одну функцию.

function Show-Url { param([string] $name) Write-Output "https://www.$name.ru" } function Show-Hoster { Write-Output "https://www.beget.com" }

# main.ps1 Import-Module "$PSScriptRoot\mod" -Force Show-Url "heihei" Show-Hoster

.\main.ps1

https://www.heihei.website https://www.beget.com

Обе функции успешно импортировались (благодаря -Force) и видны в Get-Module

Get-Module mod

ModuleType Version PreRelease Name ExportedCommands ---------- ------- ---------- ---- ---------------- Script 0.0 mod {Show-Hoster, Show-Url}

С помощью Export-ModuleMember мы можем управлять тем какие функции можно импортировать а какие нет.

function Show-Url { param([string] $name) Write-Output "https://www.$name.ru" } function Show-Hoster { Write-Output "https://www.beget.com" } Export-ModuleMember -Function Show-Hoster

.\main.ps1

Show-Url: C:\AutoTest\sandbox\vbox\demo\modules\main.ps1:5 Line | 5 | Show-Url "heihei" | ~~~~~~~~ | The term 'Show-Url' is not recognized as a name of a cmdlet, function, script file, or executable program. Check the spelling of the name, or if a path was included, verify | that the path is correct and try again. https://www.beget.com

Функция Show-Url больше не доступна.

Get-Module mod

ModuleType Version PreRelease Name ExportedCommands ---------- ------- ---------- ---- ---------------- Script 0.0 mod Show-Hoster

Show-Hoster по-прежнему работает.

# main.ps1 Import-Module "$PSScriptRoot\mod" -Force Show-Hoster

.\main.ps1

https://www.beget.com

ModuleManifest

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

Это удобно если функций в модуле становится слишком много.

Рассмотрим проект со следующей структурой

modules/ ├── main.ps1 └── mod ├── hoster.psm1 ├── mod.psd1 ├── mod.psm1 └── url.psm1

# hoster.psm1 function Show-Hoster { Write-Output "https://www.beget.com" } Export-ModuleMember -Function Show-Hoster

# url.psm1 function Show-Url { param([string] $name) Write-Output "https://www.$name.ru" } Export-ModuleMember -Function Show-Url

Несмотря на наличие манифеста, по-прежнему нужно явно перечислить все функции на экспорт.

function Write-Hi { Write-Output "Hi from mod.psm1!" } Export-ModuleMember -Function Write-Hi, Show-Hoster, Show-Url

Самая интересная часть это новый файл mod.psd1

@{ RootModule = 'mod.psm1' ModuleVersion = '1.0.0' Author = 'andreyolegovich.ru' NestedModules = @('hoster.psm1','url.psm1') FunctionsToExport = @('Write-Hi', 'Show-Hoster','Show-Url') }

Get-Module mod

ModuleType Version PreRelease Name ExportedCommands ---------- ------- ---------- ---- ---------------- Script 1.0.0 mod {Show-Hoster, Show-Url, Write-Hi}

Test-ModuleManifest mod\mod.psd1

ModuleType Version PreRelease Name ExportedCommands ---------- ------- ---------- ---- ---------------- Script 1.0.0 mod {Write-Hi, Show-Hoster, Show-Url}

Теперь можно вызвать все функции из main.ps1

# main.ps1 Import-Module "$PSScriptRoot\mod" -Force Write-Hi Show-Url "heihei" Show-Hoster

.\main.ps1

Hi from mod.psm1! https://www.heihei.website https://www.beget.com

Автор статьи: Андрей Олегович