PowerShell模块中的Get-Command范围

时间:2014-05-12 23:44:01

标签: powershell module scope

摘要

我想测试一个函数是否存在。我写了一个函数来为我做这个,但当我把它放在模块中时,它在模块的作用域中运行,当我想要的是它在调用它的会话范围内操作时。

说明

如果将其复制并粘贴到PowerShell提示符中,它将按预期工作。

function Test-Function($functionName) {
    $values = @(get-command -all | where {$_.Name -eq "$functionName" -and $_.CommandType -eq "Function"})
    return $values.Count -gt 0
}

此时,您可以运行test-function Get-ChildItem$false,因为这是一个cmdlet)或test-function test-function$true,因为这是一个函数)

但是,如果你要经常使用这个功能怎么办?

从模块调用Get-Command

如果将其保存在.psm1文件中并添加对Export-ModuleMember的调用以公开该功能,则有时会有效。

import Test.psm1

Test-Function Test-Function
# Returns $true

function blah() { echo "whatever" }

Test-Function blah
# Returns $false

据我所知,这是一个范围问题 - 模块有自己的范围,它看不到我在其外创建的其他函数。

变通方法

基本上,我想保存此功能以便以后在几个脚本文件中使用它 - 它听起来像是我的模块的候选者。但是,除非有这个范围问题的聪明解决方案,否则我会遇到一些糟糕的解决方法:

  1. 请勿将其放入模块中,将其放在.ps1文件中并点源。

    这就是我们现在所做的,它确实有效,如果没有其他解决办法,这可能是最难看的事情。

  2. 根本不要把它放在模块中,强迫任何想要使用它的人重新实现

    我想,这只是几行,所以这会奏效。问题是它已经在我的部署脚本中的几个地方了,如果我能把它变成一个函数那就太好了......

  3. 使用范围或脚本块或其他东西做一些奇怪的事情。

    喜欢,把它放在模块中:

    $testFuncBlock = {
        param($functionName)
        $values = @(get-command -all | where {$_.Name -eq "$functionName" -and $_.CommandType -eq "Function"})
        return $values.Count -gt 0
    }
    Export-ModuleMember -variable testFuncBlock
    

    通过点源脚本块来调用它:

    . $testFuncBlock Function-Name
    

    显然,这是一个丑陋的黑色虽然

  4. 有更好的解决方案吗?

    这就是我所能想到的。有什么东西可以让我在模块中保存它并在以后没有脚本块的情况下引用它吗?

1 个答案:

答案 0 :(得分:2)

Get-Command具有不同的行为,具体取决于PowerShell的版本。请查看参数文档中的版本特定说明。

Using the Get-Command Cmdlet

相反,我建议使用function:驱动器:

function Test-Function ($Name) {
    Test-Path -Path "function:${Name}"
}