Powershell模块中的*.psm1文件的目的是什么?

6

所以,我使用了一堆.ps1文件(每个函数一个文件)和.psd1清单文件来实现我的第一个 Powershell 模块。

我正在尝试理解 .psm1 文件的目的 - 我是否需要它们在我的模块中?

它们有什么附加价值吗?

编辑 1

这是我的.psd1文件:

@{
    ModuleVersion = "0.0.19106.59054"
    GUID = "59bc8fa6-b480-4226-9bcc-ec243102f3cc"
    Author = "..."
    CompanyName = "..."
    Copyright = "..."
    Description = "..."
    ScriptsToProcess = "vsts\config.ps1"
    VariablesToExport = @(
        "TfsInstanceUrl",
        "TfsApiVersion",
        "QANuGetRepoUrl"
    )
    NestedModules = @(
        "db\Backup-Database.ps1",
        ...
        "vsts\work\Get-WorkItems.ps1"
    )
    FunctionsToExport = @(
        "Assert-ExtractionDestFolder",
        ...
        "Write-HostIfNotVerbose"
    )
    PrivateData = @{
        PSData = @{
            ExternalModuleDependencies = "SqlServer"
        }
    }
}

就像我说的那样,每个函数都在自己的文件中。


嗨,也许这会引起您的兴趣 https://dev59.com/pW435IYBdhLWcg3w-lT2 - jspcal
你使用哪个.psd1文件的标签来列出你的.ps1文件? - user4003407
嵌套模块 - 请参见EDIT 1 - mark
1
虽然PowerShell允许将.ps1文件作为模块导入,但它们不会像.psm1文件那样创建模块。它们没有自己的会话状态,而是在父模块的范围内运行。 - user4003407
我创建模块的方式没有使用.psm1文件,这样做有什么问题吗?我会失去哪些功能?如果我将.ps1文件重命名为.psm1,我会得到什么好处? - mark
2个回答

8

.psm1 文件的目的是什么 - 我在我的模块中需要它们吗?

  • 脚本模块 中,即由 PowerShell 编写的模块(与编译的二进制 cmdlet 不同),只有 *.psm1 文件提供了与常规 *.ps1 脚本文件不同的模块特定行为(独立范围、私有命令、对导出命令的控制)。

    • 通常,脚本模块清单具有指向(主要)*.psm1 文件的 RootModule 条目;对于较小的模块,在这一个 *.psm1 文件中实现所有模块功能并不罕见。

      • 实际上,一个 单独的 *.psm1 文件也可以作为模块,但它不会与 PowerShell 的模块自动发现和自动加载功能集成。

      • 请注意,如果您直接在 RootModule 中使用常规的 *.ps1 脚本,则其定义将被加载到 调用方 的范围中,而不是模块的范围中;也就是说,您将失去模块的好处。

  • 即使在 NestedModules 清单条目中列出了常规的 *.ps1 脚本,通过使用特定条目,这些脚本也会以点运算符的方式在 模块 的上下文中被调用,并因此成为模块的一部分

    • 这在概念上等同于在 RootModule 中创建和引用一个根 *.psm1 脚本,并且 - 而不是定义一个 NestedModules 条目 - 显式地从那里*.ps1脚本进行点运算符调用。请参见底部部分。

    • 请注意,如果您在 NestedModules 中引用 *.psm1 文件,它们将真正成为嵌套模块,具有自己的作用域;嵌套模块可从封闭模块中使用,但无法向外界公开(虽然您可以使用 Get-Module -All 列出它们已加载的模块)。


NestedModules 中列出 *.ps1 文件与从 RootModule 进行点运算符调用的区别

尽管在功能上没有什么区别,但使用*.psm1RootModule来点号源化包含模块函数的*.ps1文件可以潜在地简化问题,如果您只需要点号源化位于模块目录子树中的所有*.ps1文件:

# Add this to the *.psm1 file specified in 'RootModule'

# Find all *.ps1 files in the module's subtree and dot-source them
foreach ($script in 
  (Get-ChildItem -File -Recurse -LiteralPath $PSScriptRoot -Filter *.ps1)
) { 
  . $script 
}

如果您需要按照特定顺序加载脚本,只需要脚本的子集,或想稍微加快速度(虽然我不认为速度差异会很明显),可以从RootModule *.psm1文件中单独引用每个文件,作为列在NestedModules条目中的替代方案:

# Add this to the *.psm1 file specified in 'RootModule'

# Dot-source the *.ps1 files individually.
. "$PSScriptRoot/db/Backup-Database.ps1"
# ...
. "$PSScriptRoot/vsts/work/Get-WorkItems.ps1"

以上所有方法在功能上是等效的。 鉴于您通过 ExportedFunctions 条目显式导出函数(这是可取的),必须点源化的 *.ps1 文件最终只是一个不相关于命令发现和模块自动加载目的的实现细节 - 它只在实际导入时才有关。


2

.psm1文件是PowerShell模块文件。当我们创建脚本模块时,将所有模块函数写入.psm1文件中,然后导出这些函数,之后我们可以通过导入模块来使用这些函数。 .psm1基本上指的是PowerShell模块。PowerShell直接识别在此文件中编写的任何内容都将是模块的一部分。

“Original Answer”翻译成“最初的回答”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接