点源函数从函数内部的文件到全局范围

时间:2013-03-03 16:00:07

标签: powershell

我想从文件中导入外部函数,而不是将其转换为模块(我们有数百个每个函数的文件,所以将它们视为模块是过度的)。

这是代码说明。请注意我在Import-Function中有一些额外的逻辑,比如添加脚本根文件夹并检查文件是否存在并抛出特殊错误,以避免每个需要这种导入的脚本中的代码重复。

C:\库\ Foo.ps1:

Function Foo {
    Write-Host 'Hello world!'
}

C:\ InvocationTest.ps1:

# Wrapper func
Function Import-Function ($Name) {
    # Checks and exception throwing are omitted
    . "C:\Repository\$name.ps1"

    # Foo function can be invoked in this scope
}

# Wrapped import
Import-Function -Name 'Foo'
Foo          # Exception: The term 'Foo' is not recognized

# Direct import
. "C:\Repository\Foo.ps1"
Foo          # 'Hello world!'

将来源点到全球范围有什么诀窍吗?

3 个答案:

答案 0 :(得分:5)

您无法使脚本在父作用域中运行,但您可以通过显式作用域来在全局作用域中创建一个函数。

这样的事情对你有用吗?

# Wrapper func
Function Import-Function ($Path) {
    # Checks and exception throwing are omitted
    $script = Get-Content $Path
    $Script -replace '^function\s+((?!global[:]|local[:]|script[:]|private[:])[\w-]+)', 'function Global:$1'
    .([scriptblock]::Create($script))

}

The above regex仅定位根函数(左对齐函数;单词function左侧没有空格)。为了定位所有函数,无论间距(包括子函数)如何,将$Script -replace行更改为:

$Script -replace '^\s*function\s+((?!global[:]|local[:]|script[:]|private[:])[\w-]+)','function Global:$1'

答案 1 :(得分:2)

您可以更改点源文件中定义的函数,以便在全局范围内定义它们:

function Global:Get-SomeThing {
    # ...
}

当你从函数中点源时,点源文件中定义的函数将是全局的。不是说这是最好的主意,只是另一种可能性。

答案 2 :(得分:0)

我现在不记得在全局范围内运行函数的方法。你可以这样做:

$name = "myscript"

$myimportcode= {
    # Checks and exception throwing are omitted
    . .\$name.ps1
    # Foo function can be invoked in this scope
}

Invoke-Expression -Command $myimportcode.ToString()

将scriptblock转换为字符串.ToString()时,变量将展开。