Работа с модулями 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
.

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

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

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

Импорт модулей
Существует множество способов начать использовать модули. Вы можете вручную импортировать модуль, используя путь к файлам модуля. Это позволяет вам тестировать и обновлять модуль без особых усилий. Но это не обеспечивает высокой переносимости, поскольку вам придется использовать точный путь к модулю. 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, в котором есть свои модули, включенные в собственные пути модулей.

$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, но вы попытаетесь его импортировать.

Чтобы импортировать удаленный модуль, сначала нужно создать PSSession. Вы можете использовать New-PSSession
для создания сессии. Затем вы бы импортировали доступный удаленному устройству модуль, используя параметр PSSession с Import-Module
.
Использование этого метода импорта удаленных модулей позволяет ускорить выполнение кода в распределенной среде. Например, если вы работаете с компьютера, а серверы, на которых вы работаете, находятся в разных частях США, выполнение определенных команд локально на серверах может занять значительно больше времени. В то время как выполнение команд на сервере и передача вывода обратно в вашу локальную сессию гораздо быстрее.
Добавление префикса модуля
Вы также можете добавить префикс к функциям, импортированным с удаленной машины. Эта опция доступна при импорте локальных модулей, но редко используется за пределами тестирования разных версий модуля бок о бок.
Если вы запустите вышеуказанную команду импорта и это будет то, что вы увидите при просмотре команд:

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

Еще одно применение 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 в начале своего модуля, но может возникнуть конфликт с другим именем модуля.
С использованием этих рекомендаций, если у вас есть группа функций, связанных с взаимодействием с реестром, вы можете иметь что-то вроде:
Манифесты модулей
Чтобы дополнить текстовый файл модуля, вы также можете включить манифест модуля. Эти файлы имеют расширение PSD1 и содержат метаданные о модуле. Здесь вы можете указать информацию об авторе, описание модуля, другие требуемые модули и множество других атрибутов. Для публикации в репозиторий требуется заполнить поля Author
и Description
.
Вот пример манифеста, который может быть у нас для модуля реестра:
Хотя это может показаться запутанным сначала, у Microsoft есть удобная командлета, которую вы можете использовать для создания файла манифеста модуля. Включенная команда – New-ModuleManifest
. Чтобы создать указанный выше манифест, вы можете использовать следующее:
Внешние файлы справки
В некоторых модулях вы также можете видеть внешние файлы справки. Их можно идентифицировать по наличию в конце имени файла <ИмяМодуля>-Help.xml. Эти внешние файлы справки содержат ту же информацию, которая обычно содержится в справке на основе команд, которую вы можете найти в определении функции.
Это также потребует добавления # .ExternalHelp <ПутьКМодулю>-Help.xml
в вашу функцию, чтобы она работала правильно при использовании команды Get-Help
после импорта модуля. Внешние файлы справки обычно присутствуют только в очень больших модулях и поэтому выходят за рамки данного объяснения.
Связанные файлы
Хотя это наиболее распространенные типы файлов, которые вы увидите в модуле, это не единственные файлы. Иногда помимо текстового модуля вы можете увидеть бинарные файлы, так как в модуле могут быть другие зависимости. Исследуя пути модуля, вы можете найти много примеров дополнительных типов файлов в модулях.
Чтобы правильно опубликовать нестандартные файлы модуля, вы должны включить другие файлы в параметре FileList
вашего файла манифеста модуля.
В модуле манифеста вы заметите множество других параметров, которые в настоящее время пусты. Вы можете использовать их для определения других требований к использованию вашего модуля. Например, вы можете определить версии PowerShell, с которыми может работать модуль. Если вы попытаетесь импортировать модуль на не поддерживаемой версии PowerShell, вы увидите следующее:

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

По умолчанию у вас будет только одна запись и она будет для PowerShell Gallery. Вы можете заметить, что она помечена как недоверенная. Это потому, что PowerShell предупреждает вас о том, что при использовании PowerShell Gallery вы можете использовать код, который не был написан и одобрен Microsoft. Это означает, что перед установкой каких-либо модулей из него вам нужно будет дать явное разрешение.
Добавление PSRepositories
Вы также можете добавить свои собственные репозитории. Чтобы доверять PowerShell Gallery, вы можете выполнить команду Get-PSRepository -Name PSGallery | Set-PSRepository -InstallationPolicy Trusted
или принять предупреждение при первой установке модуля из PowerShell Gallery.
Все команды, которые вы используете для взаимодействия с этими PSRepositories, можно найти в модуле PowerShellGet. Вы можете увидеть функции здесь:

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

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

Вы также можете определить версию модуля с помощью параметров MinimumVersion
, MaximumVersion
или RequiredVersion
.
Чтобы увидеть все установленные модули с помощью Install-Module
, вы можете использовать Get-InstalledModule
. Это позволит отобразить все модули, установленные в области AllUsers
или в вашей области CurrentUser
.
Удаление модулей
Как и установка модуля, вы можете также удалить модуль. Если модуль не был установлен с помощью команды Install-Module
, вы не сможете удалить его с помощью команды Uninstall-Module
.

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

Несмотря на то, что вы удалили VMware.PowerCLI, вы видите, что все равно осталось много зависимостей. Если вы хотите удалить все модули, вы можете использовать Get-InstalledModule VMware.* | Uninstall-Module -Force
.
Причина, по которой у вас такие сложности с полным удалением этого модуля, заключается в том, что он имеет множество зависимостей. Кроме того, некоторые из этих модулей являются зависимостями друг друга, поэтому требуется параметр Force
.
Обновление модулей
Теперь, когда вы знаете, как устанавливать и удалять модуль, вам может быть интересно, как обновить установленный модуль.
Как и в других процессах, если модуль не был установлен с помощью Install-Module
, вы не можете обновить его с помощью команд PowerShell. Вы можете использовать Update-Module
, чтобы обновить модуль до самой новой версии или до новой конкретной версии.
Также есть параметр AllowPreRelease
, который позволяет вам обновиться до версии, которая еще не была официально выпущена. Иногда это может быть полезно, так как могли быть исправлены ошибки, с которыми вы столкнулись, или добавлена новая функция, которую вы хотели бы использовать.

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

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

Это хороший пример того, как иногда в модуле могут быть включены нестандартные файлы, такие как пользовательское соглашение о лицензировании.
Создание собственного модуля
Теперь вы увидели, как взаимодействовать с модулем кого-то другого. Теперь хотите научиться создавать свой собственный, чтобы начать оптимизировать свой код для масштабируемости.
Создание файлов шаблонов
Сначала вам нужно создать папку для всех файлов вашего модуля. После создания контейнера вам нужно создать файл вашего модуля. Убедитесь, что имя файла модуля совпадает с именем папки, иначе при попытке публикации модуля PowerShell не обнаружит его правильно.
Теперь вы также хотите использовать манифест, вам также нужно назвать его так же, как контейнер и файл модуля.
С контейнером, файлом модуля и файлом манифеста у вас есть полностью функциональный модуль. Вы можете опубликовать этот модуль в PSRepository и начать устанавливать его в любом месте. Хотя, поскольку файл модуля пуст, он, вероятно, не принесет вам много пользы. Вы все равно можете использовать эти файлы для тестирования публикации, чтобы убедиться, что ваш репозиторий работает.
Регистрация PSRepository
Прежде чем вы сможете опубликовать свой модуль, вам нужно добавить еще один PSRepository в вашу сессию. Для тестирования вы можете использовать локальный путь в качестве вашего PSRepository, так как его легко настроить и удалить.
Обычно, если бы вы настраивали PSRepository с помощью каталога, вы бы хотели убедиться, что к нему есть доступ с нескольких компьютеров. Вы можете создать локальный репозиторий таким образом:
Если вы только скачиваете из PSRepository и никогда не публикуете, вы можете исключить параметр PublishLocation
.
Публикация вашего модуля
Поскольку вы уже установили политику установки как доверенную, вам не будет предложено подтверждение для установки модуля из репозитория. Теперь, когда у вас есть новый PSRepository, вы можете опубликовать свой модуль, используя Publish-Module -Name .\Scripts\ATARegistry -Repository LocalRepo
.
После публикации модуля вы можете использовать указанные выше команды для поиска модуля и его установки.
Теперь, когда вы установили модуль, вы можете использовать Get-Module
, чтобы увидеть, как модуль импортирован в вашу локальную сессию. Поскольку вы не добавили никаких функций в массив FunctionsToExport
в манифесте, свойство ExportedCommands
пусто.

Добавление в ваш модуль
Теперь, когда вы знаете, как опубликовать и установить модуль, вы можете начать добавлять в него некоторый функционал. Вы можете добавить функцию для возврата ключа реестра, чтобы это выглядело так:
Если вы оставите манифест без изменений и попытаетесь загрузить свой новый модуль, вы столкнетесь с двумя проблемами. Во-первых, вы получите ошибку, указывающую на то, что версия вашего модуля уже существует в вашем репозитории. Это происходит потому, что вы не изменили версию модуля в файле манифеста.
Экспорт функций модуля
Другая проблема заключается в том, что после импорта модуля вы по-прежнему не увидите никаких функций в свойстве ExportedCommands
, потому что вы не добавили вашу новую функцию в манифест.
Хотя вашу функцию можно использовать без указания ее в списке FunctionsToExport
, это сделает ее гораздо сложнее найти.
Если вы не определите пустой массив
@()
для вашего параметраFunctionsToExport
, то все функции, переменные и псевдонимы будут экспортированы по умолчанию.
Чтобы исправить эти две проблемы, вы можете обновить файл вашего модуля следующим образом:
Теперь, когда вы добавили функцию в свой модуль и обновили манифест, отражающий эти изменения, вы можете опубликовать новую версию модуля, используя ту же команду, что и раньше.
Выбор между 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
вы загружаете обновление, которое только что опубликовали в репозитории.

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

Get-Help
Как видите, здесь действительно нет много информации, и немного информации, которую вы получаете, вероятно, не будет полезной для кого-либо.
Вы можете добавить комментарий-основанную справку в ваш файл модуля, чтобы заполнить эти поля в системе справки. Вы можете прочитать о всех вариантах комментарий-основанной справки, используя команду Get-Help about_Comment_Based_Help
.
На данный момент вы можете обновить вашу функцию следующим образом. Это список наиболее часто используемых вспомогательных параметров, но все они по-прежнему необязательны, и можно добавить другие.
Теперь ваша функция выглядит так:
Есть некоторые специальные вспомогательные параметры, такие как .FORWARDHELPTARGETNAME. Этот параметр перенаправляет все входящие запросы справки на другую команду. Это может быть использовано в случае, когда справка должна отображать одну и ту же информацию для нескольких команд.
Теперь, когда вы добавили справку, вы можете обновить версию в манифесте модуля, опубликовать новую версию и обновить установленную версию для вашей сессии, как вы делали ранее.
Если вы сейчас посмотрите справку для функции, вы увидите, что доступно гораздо больше информации. Это отличный способ включить документацию о том, как использовать функции, особенно для кого-то, кто имеет меньше опыта и не может быстро понять, что делает модуль, глядя на код.

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

Если вернуться к пути вашего PSRepository, который вы создали ранее, вы увидите несколько файлов NUPKG. Будет по одному файлу для каждой опубликованной версии. Это сжатые версии того, что вы опубликовали при использовании Publish-Module
.
Резюме
Как только вы овладеете консолью PowerShell, самим языком PowerShell и написанием сценариев, создание собственных модулей станет последним шагом. Модули позволяют вам начать разрабатывать полезные инструменты в PowerShell. Если модули разработаны и созданы правильно, создавая модули для одной цели, вы с течением времени будете писать все меньше и меньше кода. Вы начнете ссылаться на функции своего модуля в другом коде и развиваться оттуда.
Функции модуля позволяют абстрагировать код, который вы постоянно повторяете в сценариях. Они представляют собой “метки”, на которые можно ссылаться позже в коде и вызывать в любое время, вместо того чтобы каждый раз изобретать велосипед и пытаться выяснить, как вы уже достигли своей цели ранее. Модули – это конечная “упаковка” кода PowerShell, которая группирует вместе похожий код, чтобы не тратить время на проблемы, которые вы уже решали.