2014-01-06 5 views
5

У меня есть модуль PowerShell, который инкапсулирует ряд часто используемых бизнес-функций. Его обычно не вызывают из консоли; скорее, его функции вызываются автоматическими сценариями развертывания и управления, которые импортируют модуль.Прохождение через -Вербосовое состояние командлетов модуля

Модуль включает функцию регистрации, которая записывает и в централизованное место ведения журнала. Я также хотел бы подключиться к функции Write-Verbose для записи на консоль.

#'Start Script.ps1 
#'---------------- 

import-module Corporate 
Write-Logger 'Foo' 

Мое ограничение в том, что - внутри модуля корпоративной PowerShell - мне нужно, чтобы определить, был ли Script.ps1 вызван с параметром -verbose. В идеале, я хотел бы, чтобы код определения полностью находился внутри самого модуля.

Вот пример:

[CmdletBinding()] 
Param() 

New-Module -Name TempModule -ScriptBlock { 
    function Test-ModuleVerbose() { 
     [CmdletBinding()] 
     Param() 

     PROCESS { 
      $vb = ($PSCmdlet.MyInvocation.BoundParameters['Verbose'] -eq $true) 
      Write-Host ("1: Module verbose preference: " + ($PSCmdlet.MyInvocation.BoundParameters['Verbose'] -eq $true)) 
      Write-Host ("2: Module verbose preference: " + $Script:VerbosePreference) 
      Write-Host ("3: Module verbose preference: " + $VerbosePreference) 
     } 
    } 
} | Out-Null 

function Test-Verbose() { 
    [CmdletBinding()] 
    Param() 

    PROCESS { 
     Write-Host ("Verbose preference: $VerbosePreference") 
     Test-ModuleVerbose 
    } 
} 

Test-Verbose 

Сохранить выше как Test.ps1. При вызове из консоли:

PS C:\temp> .\test.ps1 
Verbose preference: SilentlyContinue 
1: Module verbose preference: False 
2: Module verbose preference: 
3: Module verbose preference: SilentlyContinue 

PS C:\temp> .\test.ps1 -Verbose 
VERBOSE: Exporting function 'Test-ModuleVerbose'. 
VERBOSE: Importing function 'Test-ModuleVerbose'. 
Verbose preference: Continue 
1: Module verbose preference: False 
2: Module verbose preference: 
3: Module verbose preference: SilentlyContinue 

Как вы можете видеть, переменная $ VerbosePreference не доступна внутри модуля. Есть ли способ извлечения из модуля, вызван ли вызывающий скрипт флагом -Verbose.

+0

Вы можете объявить параметр switch для скрипта, а затем в зависимости от его значения установить некоторую глобальную переменную. Также вы можете установить/отключить переменную среды и проверить ее значение в командлете. – Ievgen

ответ

7

Существует переменная с именем $ VerbosePreference, которую вы можете проверить, чтобы увидеть, как обрабатывать вывод Verbose. Однако то, что дает вам проблемы, заключается в том, что скрипты загружаются в отдельную область. Если вы читали Get-Help about_scopes, вы увидите:

Script: 
    The scope that is created while a script file runs. Only 
    the commands in the script run in the script scope. To 
    the commands in a script, the script scope is the local 
    scope.

Вы можете добавить скрипт в текущей области вместо используя точечный источник обозначения. Из того же файла справки, под заголовком Использование Dot Source Notation с Scope указывается, что:

Scripts and functions follow all the rules of scope. You create them in a 
particular scope, and they affect only that scope unless you use a cmdlet 
parameter or a scope modifier to change that scope. 

But, you can add a script or function to the current scope by using dot 
source notation. Then, when a script runs in the current scope, any 
functions, aliases, and variables that the script creates are available 
in the current scope.

Я предлагаю прочитать вверх больше о прицелов в Get-Help about_scopes справочной главе.

Для быстрой проверки работает ли это или нет:

[CmdletBinding()] 
PARAM() 

New-Module -Name TempModule -ScriptBlock { 
    function Show-ModuleVerbosePreference 
    { 
     [CmdletBinding()] 
     PARAM() 

     Write-Host "Verbose preference in module function: $VerbosePreference" 
    } 
} | Out-Null 

function Show-ScriptVerbosePreference 
{ 
    [CmdletBinding()] 
    PARAM() 

    Write-Host "Verbose preference in script function: $VerbosePreference" 
} 

Show-ScriptVerbosePreference 
Show-ModuleVerbosePreference

И если попытаться назвать этот файл сценария, используя различные методы, которые мы получаем следующий вывод:

PS C:\> .\verbosity.ps1 
Verbose preference in script function: SilentlyContinue 
Verbose preference in module function: SilentlyContinue 

PS C:\> .\verbosity.ps1 -Verbose 
VERBOSE: Exporting function 'Show-ModuleVerbosePreference'. 
VERBOSE: Importing function 'Show-ModuleVerbosePreference'. 
Verbose preference in script function: Continue 
Verbose preference in module function: SilentlyContinue 

PS C:\> . .\verbosity.ps1 
Verbose preference in script function: SilentlyContinue 
Verbose preference in module function: SilentlyContinue 

PS C:\> . .\verbosity.ps1 -Verbose 
VERBOSE: Exporting function 'Show-ModuleVerbosePreference'. 
VERBOSE: Importing function 'Show-ModuleVerbosePreference'. 
Verbose preference in script function: Continue 
Verbose preference in module function: Continue

Итак, используя то мы добавили область сценария в текущую область видимости, которая, как представляется, делает настройку VerbosePreference видимой в модульном методе.

+0

Спасибо @ robert.westerlund. Не думаю, что я правильно объяснил. Я знаю, как проверить, установлен ли флаг Verbose внутри скрипта. Мне нужно, чтобы проверить - изнутри модуля PowerShell - посмотреть, был ли сценарий выведен с флагом Verbose. Я обновил свой вопрос, чтобы объяснить это лучше. – Dan

+0

Извините, я пропустил вас. Я думаю, что вам нужно будет изучить область действия PowerShell. Я уточню свой ответ. –

+1

Спасибо @ robert.westerlund. Я думаю, что точечные сценарии, вероятно, самые близкие, которые я собираюсь получить. Кажется странным, хотя, учитывая, что модуль предназначен для повторного использования бит кода, вызванного из многих мест, вы бы подумали, что можно будет выбрать переменные сценария. Спасибо за помощь. – Dan

0

Попробуйте метод ContainsKey:

$PSCmdlet.MyInvocation.BoundParameters.ContainsKey('verbose') 
+0

При выполнении внутри модуля коллекция BoundParameters всегда кажется пустой. – Dan

+0

Вы поместили команду внутри функции? –

0

В моей .psm1, я помещаю команду, подобную этой:

If ((Get-PSCallStack) [1] .Arguments -как «* Verbose = True * ') {Write-Host «Сценарий .ps1, импортирующий этот модуль, является Verbose'};

Вы можете использовать блок сценария для установки переменной, например $ VerbosePreference в области вашего модуля, или вашей собственной уникальной переменной для вашей собственной логики.

3

Можно передать большинство общих параметров с использованием сопоставимых переменных предпочтений и синтаксиса, подобного этому, -Parameter:$ParameterPreference. Итак, для конкретного случая verbose синтаксис равен -Verbose:$VerbosePreference.

Есть несколько исключений:

  • Debug: значение $DebugPreference автоматически передается сквозной, , но с указанием-Debugпереключатель силы$DebugPreferenceвInquire.
  • WhatIf: автоматически передается.

Я изменил пример кода OP следующим образом:

[CmdletBinding(SupportsShouldProcess=$true)] 
param(
    [Switch]$FullPassThru 
) 

New-Module -Name TempModule -ScriptBlock { 
     function Test-ModuleVerbose 
     { 
      [CmdletBinding(SupportsShouldProcess=$true)] 
      param() 

      Write-Host "1: Module: verbose parameter is bound : $($PSCmdlet.MyInvocation.BoundParameters['Verbose'])" 
      Write-Host "2: Module: verbose preference   : $VerbosePreference" 

      # Write-Verbose will just work without any change 
      Write-Verbose "Verbose" 

      # Other commands need the $VerbosePreference passed in 
      Set-Item -Path Env:\DEMONSTRATE_PASS_THRU ` 
        -Value 'You can safely delete this variable' ` 
        -Verbose:$VerbosePreference 
     } 

     function Test-ModulePreferencePassThru 
     { 
      [CmdletBinding(SupportsShouldProcess=$true)] 
      param() 

      Write-Debug "DebugPreference: $DebugPreference" 
      Write-Warning "WarningPreference: $WarningPreference" 
      Write-Error "ErrorActionPreference: $ErrorActionPreference" 

      Set-Item -Path Env:\DEMONSTRATE_PASS_THRU ` 
        -Value 'You can safely delete this variable' ` 
        -Verbose:$VerbosePreference ` 
        -WarningAction:$WarningPreference ` 
        -ErrorAction:$ErrorActionPreference 
     } 
    } | Out-Null 

function Test-Verbose 
{ 
    [CmdletBinding(SupportsShouldProcess=$true)] 
    param() 

    Write-Host ("Verbose preference: $VerbosePreference") 
    Test-ModuleVerbose -Verbose:$VerbosePreference 
} 

function Test-PreferencePassThru 
{ 
    [CmdletBinding(SupportsShouldProcess=$true)] 
    param() 

    Test-ModulePreferencePassThru -Verbose:$VerbosePreference 
} 

try 
{ 
    if ($FullPassThru -eq $false) 
    { 
     # just demonstrate -verbose pass-through 
     Test-Verbose 
    } 
    else 
    { 
     # most of the preferences can be explicitly passed-through, however: 
     # 
     # -Debug : $DebugPreference is automatically passed-through 
     #   and -Debug forces $DebugPreference to 'Inquire' 
     # -WhatIf : automatically passed-through 
     Test-ModulePreferencePassThru -Verbose:$VerbosePreference ` 
             -WarningAction:$WarningPreference ` 
             -ErrorAction:$ErrorActionPreference | Out-Null 
    } 
} 
finally 
{ 
    # cleanup 
    Remove-Item -Path Env:\DEMONSTRATE_PASS_THRU -Force | Out-Null 
} 

Сохранить выше как Test.ps1. При вызове из консоли:

PS C:\temp> .\test.ps1 
Verbose preference: SilentlyContinue 
1: Module: verbose parameter is bound : False 
2: Module: verbose preference   : SilentlyContinue 

PS C:\temp> .\test.ps1 -Verbose 
VERBOSE: Exporting function 'Test-ModuleVerbose'. 
VERBOSE: Exporting function 'Test-ModulePreferencePassThru'. 
VERBOSE: Importing function 'Test-ModulePreferencePassThru'. 
VERBOSE: Importing function 'Test-ModuleVerbose'. 
Verbose preference: Continue 
1: Module: verbose parameter is bound : True 
2: Module: verbose preference   : Continue 
VERBOSE: Verbose 
VERBOSE: Performing the operation "Set Item" on target "Item: DEMONSTRATE_PASS_THRU Value: You can safely delete this variable". 

Кроме того, сквозной для $DebugPreference, $WarningPreference и $ErrorActionPreference также работают:

PS C:\temp> $VerbosePreference = 'Continue' 
PS C:\temp> $DebugPreference = 'Continue' 
PS C:\temp> $WarningPreference = 'Continue' 
PS C:\temp> $ErrorActionPreference = 'Continue' 
PS C:\temp> .\test.ps1 -FullPassThru 
VERBOSE: Exporting function 'Test-ModuleVerbose'. 
VERBOSE: Exporting function 'Test-ModulePreferencePassThru'. 
VERBOSE: Importing function 'Test-ModulePreferencePassThru'. 
VERBOSE: Importing function 'Test-ModuleVerbose'. 
DEBUG: DebugPreference: Continue 
WARNING: WarningPreference: Continue 
Test-ModulePreferencePassThru : ErrorActionPreference: Continue 
At C:\OAASMain\Online\ContainerService\Tools\docker\test.ps1:72 char:9 
+   Test-ModulePreferencePassThru -Verbose:$VerbosePreference ` 
+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : NotSpecified: (:) [Write-Error], WriteErrorException 
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-ModulePreferencePassThru 

VERBOSE: Performing the operation "Set Item" on target "Item: DEMONSTRATE_PASS_THRU Value: You can safely delete this variable". 

-WhatIf автоматически передаются Проходной:

PS C:\temp> .\test.ps1 -FullPassThru -WhatIf 
What if: Performing the operation "Remove Item" on target "Item: DEMONSTRATE_PASS_THRU". 

Это также ручки -WarningAction и -ErrorAction:

PS C:\temp> .\test.ps1 -FullPassThru -WarningAction Ignore -ErrorAction Stop 
Test-ModulePreferencePassThru : ErrorActionPreference : Stop 
At C:\OAASMain\Online\ContainerService\Tools\docker\test.ps1:72 char:9 
+   Test-ModulePreferencePassThru -Verbose:$VerbosePreference ` 
+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : NotSpecified: (:) [Write-Error], WriteErrorException 
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-ModulePreferencePassThru 
Смежные вопросы