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

时间:2018-05-14 03:09:01

标签: function powershell scope powershell-v4.0 powershell-module

背景

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

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

但是,由于代码是模板化的,因此基本初始化函数具有相同的名称。 在我看来,只要我对事情做好准备,这不应该是一个问题,但事实证明这是一个问题。

证明问题

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

  • 更新:更新了代码,以便更好地展示其原理,尽管答案已经被接受了。

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
}

test.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都不会运行。

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

1 个答案:

答案 0 :(得分:1)

如果您没有从模块中明确导出任何内容,则会导出所有内容。

如果您希望函数仅在模块中可用(将其视为私有函数,尽管它实际上与PowerShell中的Private:范围无关),那么只需导出除了那些函数之外的所有函数。是内部的。

Export-ModuleMember是您定义要导出的内容的方式。它接受通配符,所以如果你可以用一个模式来描述公共内容,你可以在一次调用中完成它,但可以根据需要多次调用它。

一旦不再导出这些功能,它们就无法用于模块外部的代码。

您的示例对我来说有点奇怪,因为您似乎希望访问模块外部的某些模块代码,但希望它是相同的名称,但我不是一定。

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