如何在 powershell 模块中正确设置功能范围?

How to properly set function scope within a powershell module?

背景

我希望我所有的脚本和模块都基于一个模板脚本,该脚本负责一些常见的 "housekeeping" 任务。

我的一些模块是相互依赖的,所以我可能会在另一个模块中加载一个模块,即使是暂时的。

但是,由于代码是模板化的,所以基本的初始化函数具有相同的名称。 在我看来,只要我适当地确定范围,这就应该不是问题,但事实证明这是一个问题。

演示问题

下面的演示将有 1 个脚本,它加载一个模块,然后加载另一个模块。 每个模块都有加载模块时运行的初始化代码。

module.level2.psm1

# module.level2.psm1
# list of modules loaded by template code
$script:LoadModule = $null

# module housekeeping code - called from template code
function ModuleSpecificInitCode {
    Write-Host "Level 2 Code"
}

function Level2ModuleFunction {
    Write-Host "This is why I imported Level 2 module"
}

# module housekeeping code - template code
function TemplateInitCode {
    Write-Host "Level 2 Init"
    $LoadModule | % { Import-Module ".$_.psm1" }
}

TemplateInitCode 
try {
    ModuleSpecificInitCode 
} catch {
# Error handling
}

module.level1.psm1

# module.level1.psm1
# list of modules loaded by template code
$script:LoadModule = "module.level2"

# module housekeeping code - called from template code
function ModuleSpecificInitCode {
    Write-Host "Level 1 Code"
}

function Level1ModuleFunction {
    Write-Host "This is why I imported Level 1 module"
}

# module housekeeping code - template code
function TemplateInitCode {
    Write-Host "Level 1 Init"
    $LoadModule | % { Import-Module ".$_.psm1" }
}

TemplateInitCode 
try {
    ModuleSpecificInitCode 
} catch {
# Error handling
}

测试.ps1

# test.ps1
Remove-Module module.level*
Import-Module .\module.level1.psm1

当运行 test.ps1时,我收到的输出是:

PS>.\test.ps1
Level 1 Init
Level 2 Init
Level 2 Code
Level 2 Code

问题/我的问题

问题是最后一行。 2 级代码是 运行 而不是 1 级代码。

我已经尝试 localprivatescript 作为 <scope>:,但无论我做什么,Level 1 Code 都无法运行。

我在这里遗漏了什么,为什么所有模块似乎都在同一个命名空间中 运行?

如果您没有显式地从模块中导出任何内容,则会全部导出。

如果您希望某个函数仅在模块内可用(将其视为私有函数,尽管它实际上与 PowerShell 中的 Private: 作用域无关),则只需导出除内部的。

Export-ModuleMember 是您定义要导出的内容的方式。它接受通配符,因此如果您可以用模式描述什么是 public,您可以在一次调用中完成,但可以根据需要多次调用它。

一旦函数不再被导出,它们就不能用于模块外的代码。

你的例子对我来说有点奇怪,因为你似乎想要访问模块外部的一些模块代码,但希望它们是同名的,但我不确定。

在那种情况下,例如,如果 Level1 init 应该调用 Level2 模块中的代码,您可能会考虑将 -Scope Local 添加到 Import-Module 调用本身,但我不确定这是否会帮助你的情况。