Модуль Powershell прерывает загрузку на неподдерживаемых хостах

Глоссарий:

  • Хост: сеанс PowershellHost
  • Интерактив: [Environment]::UserInteractive -eq $True

Сценарий:

Создайте модуль powershell, который будет правильно и без ошибок прерываться только в случае сбоя. В этом случае некоторые команды/модули работают правильно только на полностью интерактивных узлах, таких как ISE и консоль, но не на поддельных интерактивных узлах, таких как консоль диспетчера пакетов NuGet.

Неудачное решение:

# Add value to Powershell manifest(psd1) 
# Issue: Only supports a string for the `PowerShellHostName` property. How to specify both `ConsoleHost` and `Windows PowerShell ISE Host`? Unknown if this property supports regex, and even if it does, will the behavior change since it's not documented?
@{
    ....
    # Name of the Windows PowerShell host required by this module
    # PowerShellHostName = ''
    ....
}

Неудачное решение:

# Check for interactive shell
# Issue: UserInteractive is still set in embedded shells like NuGet package manager
# console. Commands that expect user input directly often hang.
if([Environment]::UserInteractive) {
    # Do stuff, dotsource, etc
}

Неудачное решение:

# Issue: returning still leaves module loaded, and it appears in Get-Module list
# Even if value is supplied for return, powershell's return statement is 'special'
# and the value is ignored
if($Host.Name -inotmatch '(ConsoleHost|Windows PowerShell ISE Host)') {
    Write-Warning "Host [$($Host.Name)] not supported, aborting"
    return 
}

Неудачное решение:

# Issue: Module isn't loaded, so it can't be unloaded
if( $Host.Name -inotmatch '(ConsoleHost|Windows PowerShell ISE Host)' ) {
    Remove-Module ThisModuleName
}

Неудачное решение:

# Issue: Powershell module error output is just passthrough, import-module 
# still reports success, even though $Error is has more stuff than before
if( $Host.Name -inotmatch '(ConsoleHost|Windows PowerShell ISE Host)' ) {
    Write-Error "Unsupported Host:" $Host.Name
}

Раздражающее решение:

# Issue: Leaves two errors on the stack, one for the throw, one for the module not 
# loading successfully
if($Host.Name -inotmatch '(ConsoleHost|Windows PowerShell ISE Host)') {
    throw "Host [$($Host.Name)] not supported, aborting"
}

Не решение:

Force user to wrap the import every time.

Сомнительное решение:

Разделите модуль на вложенные подмодули, один для «Общего» и по одному для каждого поддерживаемого хоста. Используйте подпапку для каждого и дублируйте psd1 для каждого. Похоже, что в конечном итоге это станет кошмаром для поддержки, особенно в отношении вложенных зависимостей.

UberModule
    /ModuleCommon
        /ModuleCommon.(psd1|psm1)
    /ConsoleHostSpecific
        /ConsoleHostSpecific.(psd1|psm1)
    /IseHostSpecific
        /IseHostSpecific.(psd1|psm1)
    /etc...

Есть ли лучший способ сделать это, или это единственный способ разделить убер-модуль?


person Eris    schedule 04.12.2014    source источник


Ответы (1)


Взгляните на ключевое слово #requires, оно может предложить несколько вариантов, которые вы еще не пробовали. Я не знаю, имеет ли консоль диспетчера пакетов NuGet уникальный ShellId или нет.

#Requires –ShellId Microsoft.PowerShell

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

person kevmar    schedule 06.12.2014