Объем Get-Command в модуле Powershell

Резюме

Я хочу проверить, существует ли функция. Я написал функцию, которая сделает это для меня, но когда я помещаю ее в модуль, она работает в области модуля, когда я хочу, чтобы она работала в области сеанса, который ее вызывал.

Описание:

Если вы скопируете и вставьте это в приглашение 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, так как это командлет) или test-function test-function (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 и dot-source.

    Это то, что мы делаем сейчас, и оно действительно работает, и это, вероятно, наименее уродливое дело, если нет другого обходного пути.

  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

    Очевидно, что хелла уродливая, хотя

Есть ли лучшее решение?

Это все, о чем я думаю. Есть ли что-то, что позволит мне сохранить это в модуле и ссылаться на него позже без скриптового блока?

1 ответ

Get-Command имеет другое поведение в зависимости от версии powershell. Посмотрите на примечания к версии в документации по параметрам.

http://technet.microsoft.com/en-us/library/ee176842.aspx

Вместо этого я рекомендую использовать function: drive:

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

licensed under cc by-sa 3.0 with attribution.