Превышение уровня вложенности модуля обычно является результатом случайного попадания в бесконечную рекурсию при импорте модуля (независимо от того, импортируете ли вы через Import-Module
или оператор PSv5 + using module
).
Это может произойти независимо от того, есть ли у вашего модуля манифест ; ответ на связанный вопрос показывает, как это может произойти с манифестом; Вот пример без one: следующий модуль foo.psm1
вызывает бесконечную рекурсию, которая приводит к сообщению об ошибке, которое вы видели
# Create sample module (without manifest).
@'
# Accidentally try to import the module itself.
using module .\foo.psm1
function bar { 'hi from module foo' }
'@ > foo.psm1
# This fails, because an infinite import loop is entered,
# eventually causing the nesting limit to be exceeded.
Import-Module .\foo.psm1
Зачем создавать (скрипт) модуль с манифестом - хорошая идея:
Хотя манифесты являются опциональными - автономные *.psm1
файлы могут служить модулями сами по себе - есть веских причин использовать их :
Манифест модуля - это файл *.psd1
, который сопровождает ваш файл *.psm1
и указывает важный метаданные , в частности номер версии, в виде хеш-таблицы ; для лучшего пользовательского опыта оба файла должны быть помещены в каталог с с таким же именем (например, Foo.psm1
и его манифест, Foo.psd1
, следует поместить в каталог с именем Foo
).
Используя манифестированный модуль, вы включите несколько важных вариантов использования :
You нужен манифест для правильной поддержки процессов разработки программного обеспечения вашего модуля, особенно для управления версиями.
- Это также является обязательным условием для поддержки параллельной установки нескольких версий вашего модуль.
Вам необходим манифест для автоматической загрузки связанных ресурсов, таких как другие модули или вспомогательные сборки. NET, и для определения ресурсов справки.
Вам необходим манифест для интеграции с механизмом автозагрузки модуля PowerShell : если вы поместите правильно настроенный модуль в один из каталогов, перечисленных в $env:PSModulePath
, PowerShell будет:
- Обнаружение модуля и его команд еще до его импорта.
- Импортирует его по требованию , при первой попытке вызова команды из сеанса.
Вам нужен манифест для публикации sh модуля в официальном онлайн-хранилище для модулей PowerShell, Галерея PowerShell
Чтобы быстро наметить шаги для создания модуля с манифестом :
- Создать каталог , названный для базовое имя вашего
.psm1
файла; например, Foo
- Поместите код сценария как файл
Foo.psm1
file в этот каталог. В тот же каталог, используя New-ModuleManifest
Командлет, создайте файл манифеста .psd1
с тем же базовым именем (например, Foo.psd1
)
Как минимум, обновите запись RootModule
в новом .psd1
файл, указывающий на файл .psm1
(например, RootModule = 'Foo.psm1'
)
Для интеграции с функцией автоматической загрузки поместите каталог модуля в одно из мест, перечисленных в $env:PSModulePath
; для текущего пользователя это местоположение:
- Windows PowerShell:
$HOME\Documents\WindowsPowerShell\Modules
- PowerShell [Core] v6 +:
- Windows:
$HOME\Documents\PowerShell\Modules
- Linux, macOS:
$HOME/.local/share/powershell/Modules
К поддержка обнаружения и автоматической загрузки модулей эффективно и явно контролируют и сигнализируют о том, что модуль экспортирует , лучше всего явно перечислить отдельных экспортированных членов модуля в FunctionsToExport
, CmdletsToExport
, VariablesToExport
и AliasesToExport
записи манифеста.
К упрощают создание модуля , сообщество предоставил вспомогательные модули :
Plaster
- это «генератор файлов и проектов на основе шаблонов, написанный на PowerShell», который также можно использовать для сборки модулей:
Stucco
основано на Гипс, чтобы предоставить "самоуверенный шаблон Гипса для создание высококачественных модулей PowerShell. "
- Stucco - это продвинутый инструмент, выходящий за рамки простого создания модулей, который создает целую структуру проекта, включающую
psake
задач, Интеграция CI / CD, лицензирование и создание справки.
Быстрый пример с Plaster
:
# Install Plaster for the current user, if necessary.
Install-Module Plaster -Scope CurrentUser
# Get the template for creating a new script module.
$template = Get-PlasterTemplate | Where TemplatePath -match ScriptModule
# Scaffold a module in subdirectory 'Foo'
# * This will present a series of prompts, most of them with default values.
# * IMPORTANT: Be sure to also choose 'Foo' as the module *name* when prompted,
# so that the module auto-loading feature can discover your module
# (if placed in a dir. in $env:PSModulePath) and also so that you
# you can load it by its *directory* path; e.g., Import-Module ./Foo
Invoke-Plaster -TemplatePath $template.TemplatePath -Destination Foo
# Add a test function to the `.psm1` file.
# Note:
# * This is just for illustrative purposes. In real life, you would
# obviously use an editor to add functions to your module.
# * The function must be placed *before* the `Export-ModuleMember` call in order
# to be exported.
# * As stated, it is additionally recommended to list the exported members
# *explicitly*, one by one, in the *ToExport keys of the *.psd1 file.
(Get-Content -Raw ./Foo/Foo.psm1) -replace '\r?\n\r?\n', "`n`nfunction Get-Foo { 'Hi from module Foo.' }`n" | Set-Content -Encoding utf8 ./Foo/Foo.psm1
# Import the newly created module by its *directory* path.
# IMPORTANT:
# As stated, this assumes that you specified 'Foo' as the module name, i.e.
# that your manifest's file name is 'Foo.psd1', and your script module's
# 'Foo.psm1'.
Import-Module ./Foo -Verbose -Force
'---'
# Call the test function
Get-Foo
'---'
# Invoke the module's tests.
# Note: The scaffolding creates a single test to ensure that the
# module manifest (*.psd1) is valid.
Invoke-Pester ./Foo
Вы должны увидеть вывод такие как следующее:
VERBOSE: Loading module from path 'C:\Users\jdoe\Foo\Foo.psd1'.
VERBOSE: Loading module from path 'C:\Users\jdoe\Foo\Foo.psm1'.
VERBOSE: Importing function 'Get-Foo'.
---
Hi from module Foo.
---
____ __
/ __ \___ _____/ /____ _____
/ /_/ / _ \/ ___/ __/ _ \/ ___/
/ ____/ __(__ ) /_/ __/ /
/_/ \___/____/\__/\___/_/
Pester v4.9.0
Executing all tests in './Foo'
Executing script C:\Users\jdoe\Foo\test\Foo.Tests.ps1
Describing Module Manifest Tests
[+] Passes Test-ModuleManifest 128ms
Tests completed in 375ms
Tests Passed: 1, Failed: 0, Skipped: 0, Pending: 0, Inconclusive: 0