Зачем мне нужен манифест модуля - потому что предел вложенности модуля был превышен - PullRequest
1 голос
/ 27 января 2020

Я только что получил ошибку в Powershell:

 because the module nesting limit has been exceeded. Modules can only be nested to 10 levels.

Я нашел этот и обнаружил нечто, называемое "манифестом модуля". У меня уже есть файлы модуля .psm1 - зачем мне это нужно?

Примечание: у меня нет 10 уровней модулей, у меня есть 10 модулей, все загружены одним файлом import.psm1.

1 Ответ

1 голос
/ 27 января 2020

Превышение уровня вложенности модуля обычно является результатом случайного попадания в бесконечную рекурсию при импорте модуля (независимо от того, импортируете ли вы через 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», который также можно использовать для сборки модулей:

    • Встроенный шаблон «Новый модуль PowerShell Manifest» создает каталог модулей со всеми необходимыми файлами и поддерживает Pester тесты.

    • См. это сообщение в блоге для ознакомления.

  • 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
...