PowerShell 函数从函数加载

标签 powershell powershell-module

我有一个模块,其中包含多个带有函数和模块加载器的文件。

示例函数:

函数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对于包含功能栏的文件。

接下来,我们调用函数foobar ,这会产生错误,以确定两者都不在当前范围内。虽然不是绝对必要的,但这有助于说明它们的缺席。

接下来,我们调用 loader功能。点采购后foo.ps1 ,我们看到foo成功执行,因为fooloader的当前范围内功能。使用后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/

相关文章:

azure - 用于获取过去 14 天内触发的警报报告的 Powershell 代码

powershell - 使用 GitHub 包注册表作为 PowerShell 包存储库

powershell - 将 Powershell 脚本组合成一个模块

PowerShell 使用第三方模块而不安装它

linux - 在 Linux 上运行 Powershell 脚本的问题

html - PowerShell 无序 HTML 列表

powershell - 通过 PowerShell 脚本 (.ps1) 上的快捷方式传递参数

模块中的 PowerShell .ps1 文件 cmdlet

PowerShell 模块 - 每个 cmdlet 都有单独的文件

带有参数化脚本 block 的 PowerShell 函数