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

Работа с модулями PowerShell является важной частью автоматизации PowerShell. Когда вы начинаете изучать PowerShell, первые шаги обычно сводятся к использованию отдельных команд. Это приводит к созданию сценариев, которые затем приводят к созданию функций.

Используя функции, вы можете сделать свои сценарии более модульными. Это позволяет вам использовать один и тот же код во многих местах, не копируя и не вставляя его повсюду. Использование функций позволяет вам тратить меньше времени на внесение одних и тех же изменений в один и тот же код, используемый везде. Вместо этого вы можете работать над улучшением своего кода в одном месте.

Чтобы перейти на новый уровень с функциями, вы можете объединить эти функции в модуль.

A module is a collection of functions in a text file with a psm1 extension. There are some optional additions, such as a module manifest and comment-based or external help that may also be included. These will be covered later on.

Предварительные требования

I’ll be using Windows PowerShell 5.1 in this article. If you’re using an older version or PowerShell Core, your mileage may vary as to results you see.

Взаимодействие с модулями

Когда вы открываете сеанс PowerShell, у вас сразу появляются два модуля. Первый – Microsoft.PowerShell.Utility, который содержит множество основных функций PowerShell, которые вы уже используете. Второй модуль – PSReadline. Вы можете увидеть эти начальные модули, используя команду Get-Module.

Listing modules with Get-Module

Тем не менее, это не полный список всех доступных модулей. С момента выпуска PowerShell 3, модули, установленные в системе, будут импортированы при необходимости. Если у вас установлена более старая версия PowerShell, вам потребуется использовать команду Import-Module для импорта модуля перед использованием любых команд.

Иногда все же может возникнуть необходимость использовать команду Import-Module даже в более поздних версиях. Если вы хотите импортировать модуль после его установки, вы можете использовать Import-Module следующим образом:

Importing modules with Import-Module

В то время как Get-Module покажет все импортированные модули, модули, которые еще не были импортированы, вы не увидите. Затем вы можете использовать параметр ListAvailable, чтобы показать все остальные доступные модули.

Listing all available modules with Get-Module -ListAvailable

Не все команды показываются по умолчанию

Свойство ExportedCommands содержит список всех доступных команд, экспортируемых из модуля. Возможно, вы заметите некоторые различия между этим списком и тем, что содержится в файле модуля. Экспортируемые команды – это функция, встроенная в манифест модуля, позволяющая автору скрыть функцию. Авторы модулей также могут использовать Export-ModuleMember cmdlet, но это выходит за рамки данной статьи.

Авторы модулей могут хотеть скрыть функцию, потому что она предназначена для поддержки других функций, а не для использования пользователем. Для скрытия функции автор исключает ее из массива FunctionsToExport в манифесте. Здесь вы можете увидеть расширенное представление свойства ExportedCommands.

Viewing exported commands

Импорт модулей

Существует множество способов начать использовать модули. Вы можете вручную импортировать модуль, используя путь к файлам модуля. Это позволяет вам тестировать и обновлять модуль без особых усилий. Но это не обеспечивает высокой переносимости, поскольку вам придется использовать точный путь к модулю. PowerShell также не будет автоматически импортировать модули, которые не находятся в переменной $env:PSModulePath.

Выборочный импорт команд

Вы можете использовать команду Import-Module, чтобы импортировать только определенные функции, а не весь модуль, используя параметр Function. Это может сэкономить время при импорте модулей с удаленных систем, например, модулей Office 365.

Модули для всех пользователей

Модули, установленные для всех пользователей, располагаются в папке C:\Program Files\WindowsPowerShell\Modules. Этот каталог содержит множество предустановленных модулей, включая все модули, установленные с помощью команды Install-Module с использованием области видимости по умолчанию AllUsers.

Модули текущего пользователя

Если вы устанавливаете модуль, но хотите, чтобы им пользовался только один пользователь, вы можете использовать область видимости CurrentUser. В этом случае файлы модуля будут находиться в папке “Документы” по пути C:\Users\<username>\Documents\WindowsPowerShell\Modules. Это может быть полезно в среде, где используется перенаправление папок для папки “Документы”.

В этом случае вы можете установить модуль на одном компьютере и использовать его на другом, так как оба компьютера будут использовать одну и ту же папку “Документы”.

Системные модули

Для полноты можно также отметить, что существует каталог модулей по пути C:\Windows\System32\WindowsPowerShell\1.0\Modules. Технически, модуль, размещенный в этом пути, будет импортироваться как модули из других путей, но это не рекомендуется, так как он зарезервирован для системных модулей Microsoft.

Важно название

Вы можете вручную поместить свой модуль в один из этих путей, чтобы он был доступен по умолчанию в новой сессии, но вы должны убедиться, что следуете требуемому наименованию модулей. Имя папки, в которой размещены файлы модуля, должно совпадать с именем файла модуля psm1 и манифеста модуля psd1, если таковой имеется.

Используя Get-Module -ListAvailable, о котором мы упоминали ранее, ссылается на эти пути. Вы можете увидеть все пути модулей, используя $env:PSModulePath -Split ';'. В списке могут присутствовать другие пути, отличные от показанных здесь. Многие программы добавляют свои собственные пути модулей при установке. Один из примеров – SQL, в котором есть свои модули, включенные в собственные пути модулей.

Viewing module paths with $env:PSModulePath

Также есть некоторые модули, которые требуют другого процесса установки. Одним из наиболее значимых примеров является модуль ActiveDirectory. Начиная с Windows 7 и до Windows 10 1803, его можно установить с помощью установщика Remote Server Administration Tools (RSAT).

В новых версиях Windows 10 (1809+) он доступен только через Функции по требованию. Установка RSAT устанавливает модули ActiveDirectory и многие другие, которые вы будете использовать для администрирования других ролей Windows. На серверных версиях ОС Windows эти модули устанавливаются через Server Manager.

Импорт удаленных модулей (неявное удаленное выполнение)

Есть случаи, когда нецелесообразно запускать модуль локально. Вместо этого лучше подключиться к удаленному устройству и импортировать установленный на нем модуль. Когда вы это делаете, команды фактически выполняются на удаленной машине. Это часто используется с модулями Office 365 от Microsoft. Многие из них подключаются к серверу Office 365, который затем импортирует модуль. Когда вы выполняете любые из команд, они выполняются на удаленном сервере, а затем вывод отправляется обратно в вашу сессию.

Еще одно использование импорта удаленных модулей – это когда у вас нет модуля установленного локально. Вот что вы получите, если у вас не установлен модуль ActiveDirectory, но вы попытаетесь его импортировать.

Module not installed

Чтобы импортировать удаленный модуль, сначала нужно создать PSSession. Вы можете использовать New-PSSession для создания сессии. Затем вы бы импортировали доступный удаленному устройству модуль, используя параметр PSSession с Import-Module.

PS51> $AdminServer = New-PSSession -ComputerName $AdminServerName -Credential (Get-Credential)
PS51> Import-Module -Name ActiveDirectory -PSSession $AdminServer -Prefix 'Rmt'

Использование этого метода импорта удаленных модулей позволяет ускорить выполнение кода в распределенной среде. Например, если вы работаете с компьютера, а серверы, на которых вы работаете, находятся в разных частях США, выполнение определенных команд локально на серверах может занять значительно больше времени. В то время как выполнение команд на сервере и передача вывода обратно в вашу локальную сессию гораздо быстрее.

Добавление префикса модуля

Вы также можете добавить префикс к функциям, импортированным с удаленной машины. Эта опция доступна при импорте локальных модулей, но редко используется за пределами тестирования разных версий модуля бок о бок.

Если вы запустите вышеуказанную команду импорта и это будет то, что вы увидите при просмотре команд:

Viewing all available commands in a module

В этом случае вы можете использовать префикс, чтобы показать, что это не локальный модуль. Это может быть полезно, если вы импортируете модуль, который также доступен локально. Добавление префикса уменьшает путаницу в том, где выполняется код.

Удаление модулей

Вы также можете удалить модуль из текущей сессии без использования Remove-Module. Это удаляет модуль из локальной сессии, не удаляя файлы модуля. Вы можете использовать это в случае, если вы использовали удаленную сессию для использования модуля. Вы можете использовать Remove-Module, чтобы очистить свою сессию, а затем отключить удаленную сессию.

Removing a module from the session

Еще одно применение Remove-Module – это изменение модуля, когда вы не хотите запускать новую сессию PowerShell. В этом случае вы будете использовать Remove-Module, а затем Import-Module, чтобы повторно загрузить его в вашу сессию. Кроме того, вы можете использовать параметр Force с Import-Module. Это выполнит выгрузку и загрузку модуля за вас.

Что составляет модуль PowerShell

A module can consist of one or more files. To meet the minimum requirements for a module, you must have a module file. This can be a PSM1 file or any other module file such as a binary module file. To build upon that, your psm1 should have functions defined in it, or it will not be much use to anyone.

В то время как нет требований к тому, как должны выглядеть функции или что они должны делать, есть некоторые рекомендации. Обычно предпочтительно иметь все функции в модуле, построенном вокруг одной и той же концепции.

Модули содержат функции, связанные по смыслу

Например, модуль ActiveDirectory включает только функции, которые взаимодействуют с Active Directory каким-либо образом. Обычно имена функций также содержат префикс. Вернемся к модулю ActiveDirectory в качестве примера, все существительные в именах функций начинаются с AD.

Использование этих рекомендаций помогает обнаруживать функции. Представьте, что вы только что импортировали этот новый модуль и хотите просмотреть функции по вкладкам. Это гораздо проще сделать, если все функции имеют похожую структуру имени. Хотя вы, возможно, часто видите модули, начинающиеся с PS, этот префикс официально зарезервирован только для модулей Microsoft. Возможно, вы не вызовете проблемы, если используете префикс PS в начале своего модуля, но может возникнуть конфликт с другим именем модуля.

С использованием этих рекомендаций, если у вас есть группа функций, связанных с взаимодействием с реестром, вы можете иметь что-то вроде:

function Get-ATARegistryKey {...}

function Set-ATARegistryKey {...}

Манифесты модулей

Чтобы дополнить текстовый файл модуля, вы также можете включить манифест модуля. Эти файлы имеют расширение PSD1 и содержат метаданные о модуле. Здесь вы можете указать информацию об авторе, описание модуля, другие требуемые модули и множество других атрибутов. Для публикации в репозиторий требуется заполнить поля Author и Description.

Вот пример манифеста, который может быть у нас для модуля реестра:

#Модуль манифест для модуля 'ATARegistry'
#Сгенерировано: Тайлер
#Сгенерировано: 11 августа 2019 года
@{
	#Скриптовый модуль или двоичный модуль, связанный с этим манифестом.
	RootModule = 'ATARegistry'
	#Номер версии этого модуля.
	ModuleVersion = '1.0'
	#Поддерживаемые PSEditions
	#CompatiblePSEditions = @()
	#Идентификатор, используемый для уникальной идентификации этого модуля
	GUID = 'fef619fa-016d-4b11-a09d-b222e094de3e'
	#Автор этого модуля
	Author = 'Tyler Muir'
	#Компания или поставщик этого модуля
	CompanyName = 'Adam the Automator'
	#Утверждение о авторском праве для этого модуля
	Copyright = '(c) 2019 tyler. All rights reserved.'
	#Описание функциональности, предоставляемой этим модулем
	Description = 'This is a test module.'
	#Минимальная версия движка Windows PowerShell, необходимая для этого модуля
	#PowerShellVersion = ''
	#Имя хоста Windows PowerShell, необходимого для этого модуля
	#PowerShellHostName = ''
	#Минимальная версия хоста Windows PowerShell, необходимая для этого модуля
	#PowerShellHostVersion = ''
	#Минимальная версия Microsoft .NET Framework, необходимая для этого модуля. Это требование действительно только для версии PowerShell Desktop.
	#DotNetFrameworkVersion = ''
	#Минимальная версия среды выполнения общего языка (CLR), необходимая для этого модуля. Это требование действительно только для версии PowerShell Desktop.
	#CLRVersion = ''
	#Архитектура процессора (None, X86, Amd64), необходимая для этого модуля
	#ProcessorArchitecture = ''
	#Модули, которые должны быть импортированы в глобальную среду перед импортом этого модуля
	#RequiredModules = @()
	#Сборки, которые должны быть загружены перед импортом этого модуля
	#RequiredAssemblies = @()
	#Скриптовые файлы (.ps1), которые выполняются в среде вызывающего перед импортом этого модуля.
	#ScriptsToProcess = @()
	#Файлы типов (.ps1xml), которые должны быть загружены при импорте этого модуля
	#TypesToProcess = @()
	#Файлы форматирования (.ps1xml), которые должны быть загружены при импорте этого модуля
	#FormatsToProcess = @()
	#Модули, которые должны быть импортированы в виде вложенных модулей модуля, указанного в RootModule/ModuleToProcess
	#NestedModules = @()
	#Функции для экспорта из этого модуля, для наилучшей производительности не используйте подстановочные знаки и не удаляйте запись, используйте пустой массив, если нет функций для экспорта.
	FunctionsToExport = @('Get-RegistryKey','Set-RegistryKey')
	#Командлеты для экспорта из этого модуля, для наилучшей производительности не используйте подстановочные знаки и не удаляйте запись, используйте пустой массив, если нет командлетов для экспорта.
	CmdletsToExport = @()
	#Переменные для экспорта из этого модуляVariablesToExport = '*'
	#Псевдонимы для экспорта из этого модуля, для наилучшей производительности не используйте подстановочные знаки и не удаляйте запись, используйте пустой массив, если нет псевдонимов для экспорта.
	AliasesToExport = @()
	#Ресурсы DSC для экспорта из этого модуля
	#DscResourcesToExport = @()
	#Список всех модулей, упакованных с этим модулем
	#ModuleList = @()
	#Список всех файлов, упакованных с этим модулем
	#FileList = @()
	#Личные данные для передачи модулю, указанному в RootModule/ModuleToProcess. Это также может содержать хэш-таблицу PSData с дополнительными метаданными модуля, используемыми PowerShell.
	PrivateData = @{
		PSData = @{
			#Теги, применяемые к этому модулю. Они помогают при поиске модулей в онлайн-галереях.
			#Tags = @()
			#URL-адрес лицензии для этого модуля.
			#LicenseUri = ''
			#URL-адрес основного веб-сайта для этого проекта.
			#ProjectUri = ''
			#URL-адрес иконки, представляющей этот модуль.
			#IconUri = ''
			#Примечания к версии этого модуля
			#ReleaseNotes = ''
		} 
		#Конец хэш-таблицы PSData
	} 
	#Конец хэш-таблицы PrivateData
	#URI справочной информации об этом модуле
	#HelpInfoURI = ''
	#Префикс по умолчанию для команд, экспортируемых из этого модуля. Переопределите префикс по умолчанию, используя Import-Module -Prefix.
	#DefaultCommandPrefix = ''
}

Хотя это может показаться запутанным сначала, у Microsoft есть удобная командлета, которую вы можете использовать для создания файла манифеста модуля. Включенная команда – New-ModuleManifest. Чтобы создать указанный выше манифест, вы можете использовать следующее:

PS51> New-ModuleManifest -Path .\Scripts\TestModule.psd1 -Author 'Tyler Muir' -CompanyName 'Adam the Automator' -RootModule 'TestModule.psm1' -FunctionsToExport @('Get-RegistryKey','Set-RegistryKey') -Description 'This is a test module.'

Внешние файлы справки

В некоторых модулях вы также можете видеть внешние файлы справки. Их можно идентифицировать по наличию в конце имени файла <ИмяМодуля>-Help.xml. Эти внешние файлы справки содержат ту же информацию, которая обычно содержится в справке на основе команд, которую вы можете найти в определении функции.

Это также потребует добавления # .ExternalHelp <ПутьКМодулю>-Help.xml в вашу функцию, чтобы она работала правильно при использовании команды Get-Help после импорта модуля. Внешние файлы справки обычно присутствуют только в очень больших модулях и поэтому выходят за рамки данного объяснения.

Хотя это наиболее распространенные типы файлов, которые вы увидите в модуле, это не единственные файлы. Иногда помимо текстового модуля вы можете увидеть бинарные файлы, так как в модуле могут быть другие зависимости. Исследуя пути модуля, вы можете найти много примеров дополнительных типов файлов в модулях.

Чтобы правильно опубликовать нестандартные файлы модуля, вы должны включить другие файлы в параметре FileList вашего файла манифеста модуля.

В модуле манифеста вы заметите множество других параметров, которые в настоящее время пусты. Вы можете использовать их для определения других требований к использованию вашего модуля. Например, вы можете определить версии PowerShell, с которыми может работать модуль. Если вы попытаетесь импортировать модуль на не поддерживаемой версии PowerShell, вы увидите следующее:

Requiring certain versions of PowerShell

PSRepositories

Один из основных вариантов распространения модулей – это PSRepository. С точки зрения пользователя, PSRepository – это локальное место, где несколько людей или несколько устройств могут получить доступ к файлам модуля. Часто это веб-серверы, на которых можно публиковать файлы.

Вы также можете использовать каталог в качестве репозитория, но это ограничивает функциональность вашего репозитория. Вы можете разместить PSRepository на своем сервере или воспользоваться одним из множества вариантов, доступных в Интернете, например, PowerShell Gallery. Вы можете увидеть свои PSRepositories, используя команду Get-PSRepository.

Default PowerShell NuGet repositories

По умолчанию у вас будет только одна запись и она будет для PowerShell Gallery. Вы можете заметить, что она помечена как недоверенная. Это потому, что PowerShell предупреждает вас о том, что при использовании PowerShell Gallery вы можете использовать код, который не был написан и одобрен Microsoft. Это означает, что перед установкой каких-либо модулей из него вам нужно будет дать явное разрешение.

Добавление PSRepositories

Вы также можете добавить свои собственные репозитории. Чтобы доверять PowerShell Gallery, вы можете выполнить команду Get-PSRepository -Name PSGallery | Set-PSRepository -InstallationPolicy Trusted или принять предупреждение при первой установке модуля из PowerShell Gallery.

Все команды, которые вы используете для взаимодействия с этими PSRepositories, можно найти в модуле PowerShellGet. Вы можете увидеть функции здесь:

Commands in the PowerShellGet module

Модуль PowerShellGet может потребоваться обновить перед взаимодействием с определенными репозиториями.

Поиск модулей

Еще одна ключевая возможность использования PSRepository – возможность поиска модулей. Это можно сделать с помощью команды Find-Module. Есть несколько способов фильтрации для поиска именно того, что вам нужно, но пока вы можете искать модули VMware так:

Finding modules on the PowerShell Gallery

Это покажет все модули, которые начинаются с VMware. Хотя большинство из них от VMware, вам нужно посмотреть атрибут автора, чтобы узнать, кто опубликовал модуль.

Поскольку любой может загрузить модуль в PowerShell Gallery, доступно тысячи модулей. Это означает, что вы можете найти модули, которые не работают должным образом для вашего случая использования. Многие модули, которые вы найдете, являются открытыми исходными кодами, поэтому вы можете внести свой вклад в их улучшение.

Установка модулей

Чтобы использовать команду Install-Module, вам нужно иметь доверенный PSRepository, который хранит модуль. Это может быть PowerShell Gallery, другой интернет- PSRepository или самостоятельно созданный сайт. Вы можете выполнить команду Find-Module и затем выполнять установку модуля, чтобы убедиться в его правильности.

Finding modules installed from a PSRepository

Вы также можете определить версию модуля с помощью параметров MinimumVersion, MaximumVersion или RequiredVersion.

Чтобы увидеть все установленные модули с помощью Install-Module, вы можете использовать Get-InstalledModule. Это позволит отобразить все модули, установленные в области AllUsers или в вашей области CurrentUser.

Удаление модулей

Как и установка модуля, вы можете также удалить модуль. Если модуль не был установлен с помощью команды Install-Module, вы не сможете удалить его с помощью команды Uninstall-Module.

Uninstalling modules installed from a PSRepository with Uninstall-Module

Как видите здесь, мы пытаемся удалить модуль ActiveDirectory. Поскольку этот модуль не установлен с помощью Install-Module, вы получите ошибку при попытке использовать Uninstall-Module. Чтобы удалить этот модуль, нам нужно отменить установку модуля.

Чтобы увидеть успешное удаление модуля, вы можете удалить модуль VMware.PowerCLI, который вы установили ранее.

Uninstalling a module downloaded from the PowerShell Gallery

Несмотря на то, что вы удалили VMware.PowerCLI, вы видите, что все равно осталось много зависимостей. Если вы хотите удалить все модули, вы можете использовать Get-InstalledModule VMware.* | Uninstall-Module -Force.

Причина, по которой у вас такие сложности с полным удалением этого модуля, заключается в том, что он имеет множество зависимостей. Кроме того, некоторые из этих модулей являются зависимостями друг друга, поэтому требуется параметр Force.

Обновление модулей

Теперь, когда вы знаете, как устанавливать и удалять модуль, вам может быть интересно, как обновить установленный модуль.

Как и в других процессах, если модуль не был установлен с помощью Install-Module, вы не можете обновить его с помощью команд PowerShell. Вы можете использовать Update-Module, чтобы обновить модуль до самой новой версии или до новой конкретной версии.

Также есть параметр AllowPreRelease, который позволяет вам обновиться до версии, которая еще не была официально выпущена. Иногда это может быть полезно, так как могли быть исправлены ошибки, с которыми вы столкнулись, или добавлена новая функция, которую вы хотели бы использовать.

Updating modules with Update-Module

Просмотр/Сохранение модуля

Одна из команд, которая редко используется, но очень полезна при проверке модулей перед использованием, это Save-Module. С помощью этой команды вы можете загрузить модуль по указанному пути, не устанавливая его.

Затем вы можете проверить файлы и, если модуль не является двоичным, вы можете просмотреть исходный код модуля. Это может быть полезно не только для проверки, не выполняет ли модуль нежелательные действия, но и для изучения того, как другие разрабатывают свои модули.

Downloading modules with Save-Module

В этом примере загружается модуль VMware.PowerCLI, а также все зависимости. Вот что отображается в папке VMware.PowerCLI:

VMware.PowerCLI module contents

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

Создание собственного модуля

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

Создание файлов шаблонов

Сначала вам нужно создать папку для всех файлов вашего модуля. После создания контейнера вам нужно создать файл вашего модуля. Убедитесь, что имя файла модуля совпадает с именем папки, иначе при попытке публикации модуля PowerShell не обнаружит его правильно.

PS51> New-Item -Path .\Scripts -Name ATARegistry -ItemType Directory
PS51> New-Item -Path .\Scripts\ATARegistry -Name ATARegistry.psm1

Теперь вы также хотите использовать манифест, вам также нужно назвать его так же, как контейнер и файл модуля.

PS51> New-ModuleManifest -Path .\Scripts\ATARegistry\ATARegistry.psd1 -Author 'Tyler Muir' -CompanyName 'Adam the Automator' -RootModule ATARegistry.psm1 -Description 'Used for interacting with registry keys'

С контейнером, файлом модуля и файлом манифеста у вас есть полностью функциональный модуль. Вы можете опубликовать этот модуль в PSRepository и начать устанавливать его в любом месте. Хотя, поскольку файл модуля пуст, он, вероятно, не принесет вам много пользы. Вы все равно можете использовать эти файлы для тестирования публикации, чтобы убедиться, что ваш репозиторий работает.

Регистрация PSRepository

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

Обычно, если бы вы настраивали PSRepository с помощью каталога, вы бы хотели убедиться, что к нему есть доступ с нескольких компьютеров. Вы можете создать локальный репозиторий таким образом:

PS51> New-Item -Path C:\ -Name Repo -ItemType Directory
PS51> Register-PSRepository -Name 'LocalRepo' -SourceLocation 'C:\Repo' -PublishLocation 'C:\Repo' -InstallationPolicy Trusted

Если вы только скачиваете из PSRepository и никогда не публикуете, вы можете исключить параметр PublishLocation.

Публикация вашего модуля

Поскольку вы уже установили политику установки как доверенную, вам не будет предложено подтверждение для установки модуля из репозитория. Теперь, когда у вас есть новый PSRepository, вы можете опубликовать свой модуль, используя Publish-Module -Name .\Scripts\ATARegistry -Repository LocalRepo.

После публикации модуля вы можете использовать указанные выше команды для поиска модуля и его установки.

Теперь, когда вы установили модуль, вы можете использовать Get-Module, чтобы увидеть, как модуль импортирован в вашу локальную сессию. Поскольку вы не добавили никаких функций в массив FunctionsToExport в манифесте, свойство ExportedCommands пусто.

No exported commands

Добавление в ваш модуль

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

function Get-ATARegistryKey {
    param (
        [string]$Path
    )
    Get-Item $Path
}

Если вы оставите манифест без изменений и попытаетесь загрузить свой новый модуль, вы столкнетесь с двумя проблемами. Во-первых, вы получите ошибку, указывающую на то, что версия вашего модуля уже существует в вашем репозитории. Это происходит потому, что вы не изменили версию модуля в файле манифеста.

Экспорт функций модуля

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

Хотя вашу функцию можно использовать без указания ее в списке FunctionsToExport, это сделает ее гораздо сложнее найти.

Если вы не определите пустой массив @() для вашего параметра FunctionsToExport, то все функции, переменные и псевдонимы будут экспортированы по умолчанию.

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

ModuleVersion = '1.1'
FunctionsToExport = 'Get-RegistryKey'

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

PS51> Publish-Module -Name .\Scripts\ATARegistry -Repository LocalRepo.

Выбор между FunctionsToExport и Export-ModuleMember

В PowerShell есть две похожие функции для экспорта членов модуля. Проблема состоит в выборе между ними. Оба варианта являются правильными, но один из них может подойти вам лучше, в зависимости от ваших потребностей.

Если вам нужно динамически контролировать, какие функции экспортируются, используйте Export-ModuleMember, так как вы можете передать список функций для экспорта. Обычно это используется при подключении нескольких отдельных файлов с функциями PS1. Разделив внутренние функции на приватную папку и экспортируемые функции на публичную папку, вы можете легко экспортировать их, передавая все публичные функции в функцию Export-ModuleMember.

A few notes about Export-ModuleMember:

  • Это переопределяет поведение FunctionsToExport, поэтому если используется команда Export-ModuleMember, FunctionsToExport не будет иметь эффекта.
  • Export-ModuleMember не экспортирует переменные и псевдонимы без явного определения, в отличие от FunctionsToExport, которая экспортирует эти значения.
  • Можно использовать несколько команд Export-ModuleMember, и они будут накладываться друг на друга, вместо того чтобы иметь приоритет.

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

Обновление модуля

Последним шагом будет обновление модуля в вашей сессии, чтобы можно было использовать обновленные файлы. С помощью команды Update-Module ATARegistry вы загружаете обновление, которое только что опубликовали в репозитории.

Exported commands now show up

Теперь вы можете увидеть, что у вас есть новая версия модуля, и вы можете увидеть функцию, которую вы определили в манифесте.

Создание справочного содержимого

Одна из вариантов, которые ранее были упущены, – это встроенная в PowerShell система справки. Вы, вероятно, в какой-то момент использовали команду Get-Help для функции. Эту информацию можно добавить двумя основными способами.

Первый способ – добавить комментарий-основанную справку в определение функции. Обычно это делают многие авторы модулей. Второй способ – использовать внешний файл справки. Вы можете использовать параметр Full, чтобы отобразить всю информацию из справки.

Finding help with Get-Help

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

Вы можете добавить комментарий-основанную справку в ваш файл модуля, чтобы заполнить эти поля в системе справки. Вы можете прочитать о всех вариантах комментарий-основанной справки, используя команду Get-Help about_Comment_Based_Help.

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

Теперь ваша функция выглядит так:

 function Get-RegistryKey {
	<#
	    .SYNOPSIS
	    Возвращает ключ реестра с указанным путем.
	    .DESCRIPTION
	    Функция использует команду Get-Item для возврата информации для указанного ключа реестра.
	    .PARAMETER Path
	    Путь, в котором будет осуществляться поиск ключа реестра.
	    .EXAMPLE
	    Get-RegistryKey -Path 'HKLM:\HARDWARE\DESCRIPTION\System'
	    .INPUTS
	    System.String
	    .OUTPUTS
	    Microsoft.Win32.RegistryKey
	    .NOTES
	    Этот модуль является примером того, как может выглядеть хорошо документированная функция.
	    .LINK
	
ATA Learning
#>
param( [string]$Path ) Get-Item $Path }

Есть некоторые специальные вспомогательные параметры, такие как .FORWARDHELPTARGETNAME. Этот параметр перенаправляет все входящие запросы справки на другую команду. Это может быть использовано в случае, когда справка должна отображать одну и ту же информацию для нескольких команд.

Теперь, когда вы добавили справку, вы можете обновить версию в манифесте модуля, опубликовать новую версию и обновить установленную версию для вашей сессии, как вы делали ранее.

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

Getting full help content with Get-Help

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

Если вы посмотрите в путь модуля AllUsers, вы увидите версию модуля и все файлы модуля, которые вы установили.

Folder name is the module version

Если вернуться к пути вашего PSRepository, который вы создали ранее, вы увидите несколько файлов NUPKG. Будет по одному файлу для каждой опубликованной версии. Это сжатые версии того, что вы опубликовали при использовании Publish-Module.

Резюме

Как только вы овладеете консолью PowerShell, самим языком PowerShell и написанием сценариев, создание собственных модулей станет последним шагом. Модули позволяют вам начать разрабатывать полезные инструменты в PowerShell. Если модули разработаны и созданы правильно, создавая модули для одной цели, вы с течением времени будете писать все меньше и меньше кода. Вы начнете ссылаться на функции своего модуля в другом коде и развиваться оттуда.

Функции модуля позволяют абстрагировать код, который вы постоянно повторяете в сценариях. Они представляют собой “метки”, на которые можно ссылаться позже в коде и вызывать в любое время, вместо того чтобы каждый раз изобретать велосипед и пытаться выяснить, как вы уже достигли своей цели ранее. Модули – это конечная “упаковка” кода PowerShell, которая группирует вместе похожий код, чтобы не тратить время на проблемы, которые вы уже решали.

Source:
https://adamtheautomator.com/powershell-modules/