我有一个模块,其中包含多个带有函数和模块加载器的文件。
示例函数:
函数1.ps1
function Init() {
echo "I am the module initialization logic"
}
function DoStuff() {
echo "Me performing important stuff"
}
模块加载器文件:
模块1.psm1
:
$script:Functions = Get-ChildItem $PSScriptRoot\*.ps1
function LoadModule {
Param($path)
foreach ($import in @($path)) {
. $import.FullName
}
}
LoadModule script:Functions
Init # function doesn't found
因此,我尝试通过过程 LoadModule
从文件 Function1.ps1
加载函数。
调试 LoadModule
显示加载的外部函数,但在完成 LoadModule
过程后,函数变得不可访问,因此脚本在 Init
行失败。
但是重写的模块加载器没有 LoadModule
函数工作正常
模块1.psm1
:
Get-ChildItem $PSScriptRoot\*.ps1 | %{
. $import.FullName
}
Init # In this case - all works fine
因此,据我了解从放置在某个隔离作用域中的函数加载的文件函数,并且为了能够访问它们,我需要添加一些作用域标志。
也许有人知道我应该添加什么才能使函数 Init()
可从 module.pm1 脚本主体访问,但不能使其从外部访问(不使用 Export-ModuleMember
)?
最佳答案
注意:编辑 1,对点源实际作用的澄清,包含在最后。
首先,您将函数和模块的术语和用法混合在一起。应使用 Import-Module cmdlet 将扩展名为 .psm1 的模块导入到终端中。当点采购时,就像您在这里所做的那样,您应该只定位包含函数的脚本文件,这些函数是带有 .ps1 扩展名的文件。
我对 PowerShell 也比较陌生,并且遇到了同样的问题。在花了大约一个小时阅读这个问题后,我无法找到解决方案,但我发现的很多信息都表明这是一个范围问题。因此,我使用三个文件创建了一个测试。
foo.ps1
function foo {
Write-Output "foo"
}
bar.psm1
function bar {
Write-Output "bar"
}
scoping.ps1
function loader {
echo "dot sourcing file"
. ".\foo.ps1"
foo
echo "Importing module"
Import-Module -Name ".\bar.psm1"
bar
}
foo
bar
loader
foo
bar
pause
让我们看看这个脚本的作用。
首先我们定义一个虚拟对象 loader
功能。这不是一个实用的加载器,但足以测试加载的文件中的范围和函数的可用性。该函数点获取包含函数 foo 的 ps1 文件,并使用 Import-Module
对于包含功能栏的文件。
接下来,我们调用函数foo
和bar
,这会产生错误,以确定两者都不在当前范围内。虽然不是绝对必要的,但这有助于说明它们的缺席。
接下来,我们调用 loader
功能。点采购后foo.ps1
,我们看到foo
成功执行,因为foo
在loader
的当前范围内功能。使用后Import-Module
对于 bar.psm1
,我们看到bar
也执行成功。现在我们退出 loader
的范围函数并返回主脚本。
现在我们看到 foo
的执行因错误而失败。这是因为我们点来源 foo.ps1
在函数的范围内。但是,因为我们导入了bar.psm1
, bar 成功执行。这是因为模块默认导入到全局范围中。
我们如何利用它来改善您的 LoadModule
功能?此功能的主要内容是您需要切换到使用模块来执行导入的函数。请注意,根据我的测试,您无法导入模块加载器功能;仅当您不获取加载程序时,这才有效。
LoadModule.ps1
function LoadModule($Path) {
Get-ChildItem -Path "$Path" -Filter "*.psm1" -Recurse -File -Name| ForEach-Object {
$File = "$Path$_"
echo "Import-Module -Name $File"
Import-Module -Name "$File" -Force
}
}
现在在终端中:
. ".\LoadModule.ps1"
LoadModule ".\"
foo
bar
编辑 1:对点来源的进一步说明
点源相当于将指定文件的内容复制粘贴到执行点源的文件中。执行操作的文件逐字“导入”目标的内容,在继续执行“导入”代码之前不执行任何其他操作。例如
foo.ps1
Write-Output "I am foo"<br/>
. ".\bar.ps1"
bar.ps1
Write-Output "I am bar"
有效
Write-Output "I am foo"
Write-Output "I am bar"
关于PowerShell 函数从函数加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57267958/