Разработка и распространение модуля на Powershell
Несмотря на то, что в интернете вы можете найти очень много различных инструкций по поводу того, как создать свой собственный Powershell-модуль, даже официальная документация не дает полного понимания, как все-таки создать модуль правильно.
Я потратил несколько часов на изучение разных статей и, как обычно, пришел к своему подходу, который мне кажется достаточно удобным, гибким, и которым я хочу поделиться сейчас.
Придумайте название
Это важно :-). Потом с этим названием вы будете долго жить, поэтому придумайте то, что вам потом будет приятно видеть каждый день =).
В моем случае я решил придерживаться следующего подхода: <код_заказчика\название заказчика>.<код_проекта>.Powershell
.
Для целей этого гайда давайте делать модуль My.OwnModule.Powershell
.
Придумайте префикс для названия командлетов\функций
Если вы разрабатываете несколько разных модулей (например, для разных компаний или команд), иногда в модулях может быть одна и та же функция. И если вы начнете сами использовать эти модули одновременно, при их импорте начнутся конфликты имен. Поэтому имеет смысл использовать для каждого модуля свой уникальный префикс.
В нашем примере я буду использовать MyOwn
. Например стандартное имя New-Item превратится в New-MyOwnItem.
Установите необходимые утилиты
Кроме самого Powershell, Вам понадобится утилита командной строки nuget
. Она будет нужна, чтобы паковать модуль в nuget-пакет и распространять модуль между другими компьютерами\пользователями.
Создайте дерево каталогов
Кроме корневой папки, которая будет называться так же, как и сам модуль, понадобится начальный набор каталогов.
D:.
└───My.OwnModule.Powershell
├───images
├───private
├───public
│ └───common
└───_bin
- images. Тут будет лежать иконка для пакета, которая в теории будет видна в каком-нибудь репозитории типа Artifactory.
- private. Тут будут лежать скрипты, которые должны быть доступны только для служебных нужд. Например, чтобы прочитать файл с диска с обработкой ошибок.
- public. Тут будут лежать скрипты, в которых будут доступны непосредственно пользователям модуля.
- public -> common. Эта папка нужна исключительно для структурирования и группировки файлов. Все внутри Public будет читаться рекурсивно.
- _bin. Тут будут лежать пакеты с модулем, когда утилита nuget скомпилирует пакет.
Создайте необходимые файлы
Также нужно создать файлы, которые собственно и превращают набор Powershell-сриптов в модуль.
D:.
│ LICENSE
│ PSScriptAnalyzerSettings.psd1
│ README.md
│
└───My.OwnModule.Powershell
│ local-build.ps1
│ local-install.ps1
│ My.OwnModule.Powershell.nuspec
│ My.OwnModule.Powershell.psd1
│ My.OwnModule.Powershell.psm1
│
├───images
│ icon.png
│
├───private
│ _stub.ps1
│
├───public
│ └───common
│ Read-MyOwnJsonFile.ps1
│
└───_bin
Нас интересуют файлы, которые лежат в корневой папке модуля, в private и public. Остальные - это служебные файлы git-репозитория. Ниже привожу содержимое каждого файла с комментариями.
Заполняем служебные файлы для Powershell-модуля
My.OwnModule.Powershell.nuspec
Этот файл нужен, чтобы nuget
генерировал пакет.
<?xml version="1.0" encoding="utf-8"?>
<package >
<metadata>
<id>My.OwnModule.Powershell</id>
<version>0.0.2</version>
<authors>Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. </authors>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<icon>images\icon.png</icon>
<description>
There is no any description available at this time. Sorry for that.
</description>
<releaseNotes>Initial release.</releaseNotes>
<tags>PSEdition_Core PSEdition_Desktop Linux Mac PSModule PSIncludes_Cmdlet</tags>
</metadata>
</package>
My.OwnModule.Powershell.psd1
Этот файл - манифест, описание модуля с точки зрения самого Powershell. Тут хранятся различные сведения об авторе, о функциях, которые модуль будет предосталять и т.п.
Обратите внимание на строку 11 и параметр FunctionsToExport. Это функции, которые будут доступны пользователям вашего модуля. Поэтому, при добавлении новых функций в модуль, необходимо помнить и добавлять их сюда.
@{
RootModule = "My.OwnModule.Powershell.psm1"
ModuleVersion = "0.0.2"
CompatiblePSEditions = "Desktop", "Core"
GUID = "8f37ba7b-be77-4b6e-8ceb-d30c0c328674"
Author = "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в браузере должен быть включен Javascript. "
PowerShellVersion = "7.0"
ScriptsToProcess = @();
FunctionsToExport = @(
"Read-MyOwnJsonFile"
);
CmdletsToExport = "*"
VariablesToExport = "*"
AliasesToExport = "*"
}
My.OwnModule.Powershell.psm1
Этот файл - скрипт, который выполняется, когда вы запускаете (или сама система запускает) Import-Module. Это самый главный файл в модуле, вообще говоря, это и есть сам модуль.
#Requires -Version 7.0
$public = @( Get-ChildItem -Path $PSScriptRoot\public\*.ps1 -Recurse; );
$private = @( Get-ChildItem -Path $PSScriptRoot\private\*.ps1 -Recurse; );
# Dot source the files
foreach ($import in @($public + $private))
{
try
{
Write-Verbose "Importing '$($import.FullName)'.";
. $import.FullName;
}
catch
{
Write-Error -Message "Failed to import function $($import.fullname): $_";
}
}
Export-ModuleMember -Function $public.Basename;
_stub.ps1
Я положил этот файл-заглушку, чтобы скрипт из psm1-файла смог нормально прочитать папку без возможных проблем. А вообще он полностью пустой.
Read-MyOwnJsonFile.ps1
Это файл командлета, который мы будем предоставлять нашим модулем. Обратите внимание, как он называется - Read-MyOwnJsonFile, всмысле что используется префикс для имен командлетов модуля.
local-build.ps1
Этот файл не является непосредственной частью Powershell-модуля. Это скрипт, который я использую для упаковки модуля в nuget-пакет, чтобы потом его можно было положить куда-нибудь в архив. Также этот скрипт в каждый запуск изменяет версию модуля на +1.
# Config
$moduleName = "My.OwnModule.Powershell";
# Clear old packages
# Get-ChildItem .\$moduleName\_bin | Remove-Item -Force -Verbose;
#region Get current package version and increment Patch
$version = Select-String -Path .\$moduleName\$moduleName.nuspec -Pattern "<version>(\d)\.(\d)\.(\d{1,})</version>";
[int]$majorVersion = $version | Select-Object @{name="version"; expression={$_.Matches.Groups[1].Value}} | select-object -ExpandProperty version;
[int]$minorVersion = $version | Select-Object @{name="version"; expression={$_.Matches.Groups[2].Value}} | select-object -ExpandProperty version;
[int]$patchVersion = $version | Select-Object @{name="version"; expression={$_.Matches.Groups[3].Value}} | select-object -ExpandProperty version;
$patchVersion++;
$nuspecVersionString = "<version>$majorVersion.$minorVersion.$patchVersion</version>";
$psd1VersionString = "ModuleVersion = `"$majorVersion.$minorVersion.$patchVersion`"";
#endregion /Get current package version and increment Patch
#region Update package version
$a = Get-Content -Path ".\$moduleName\$moduleName.nuspec" | %{$_ -replace "<version>(\d)\.(\d)\.(\d{1,})<\/version>", $nuspecVersionString };
$a | Out-File ".\$moduleName\$moduleName.nuspec" -Verbose;
$a = Get-Content -Path ".\$moduleName\$moduleName.psd1" | %{$_ -replace "ModuleVersion = `"\d\.\d.\d{1,}`"", $psd1VersionString };
$a | Out-File ".\$moduleName\$moduleName.psd1" -Verbose;
#endregion /Update package version
nuget pack ".\$moduleName\$moduleName.nuspec" -OutputDirectory .\$moduleName\_bin -Properties NoWarn=NU5111,NU5110,NU5100
$package = Get-ChildItem .\$moduleName\_bin\*.nupkg | Sort-Object -Property CreationTime | Select-Object -Last 1;
$package
local-install.ps1
Соответственно, этот кастомный скрипт - для установки модуля.
$moduleName = "My.OwnModule.Powershell";
$repoName = "My.OwnModule.Powershell.Repository";
$repoPath = "D:\Private\My.OwnModule.Powershell\My.OwnModule.Powershell\_bin\";
Register-PSRepository -Name $repoName -SourceLocation $repoPath -InstallationPolicy Trusted -ScriptSourceLocation $repoPath;
Install-Module -Name $moduleName -Repository $repoName -Verbose;
Get-Module $moduleName -ListAvailable;
Упаковка модуля
Попробуем запустить local-build.ps1 и посмотреть, что получится.
Отлично! Nuget-пакет готов и лежит в папке My.OwnModule.Powershell\_bin\My.OwnModule.Powershell.0.0.3.nupkg. Попробуем его установить и воспользоваться.
Установка Powershell-модуля из nuget-пакета.
Прекрасно, модуль готов к работе!
Там Verbose говорит, что версия 0.0.5 уже установлена и так далее. Это потому что я попытался понизить версию, вместо того, чтобы повысить. Не обращайте внимание.
GitHub репозиторий
Вы можете найти все эти файлы в моем репозитории: https://github.com/vicioussn/My.OwnModule.Powershell.
- Просмотров: 871