2014-01-06 90 views
5

我有一個封裝了大量常用業務功能的PowerShell模塊。通常不會從控制檯調用;相反,其功能由導入模塊的自動部署和管理腳本調用。將-Verbose狀態傳遞給模塊cmdlet

該模塊包含一個日誌記錄功能,可寫入中央記錄位置。我也喜歡寫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

您可以爲腳本聲明開關參數,然後根據它的值設置一些全局變量。您也可以設置/取消設置環境變量並在cmdlet中檢查它的值。 – Ievgen

回答

7

有一個名爲$ VerbosePreference的變量,您可以查看詳細輸出應如何處理。但是,這裏給你提出的問題是腳本被加載到一個單獨的範圍中。如果你讀了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.

您可以將腳本添加到而不是使用點源符號的電流範圍。從同一個幫助文件,標題中使用點源符號與範圍下面則指出:

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模塊中檢查腳本是否使用詳細標誌調用。我更新了我的問題以更好地解釋它。 – Dan

+0

對不起,我錯過了你。我認爲你需要研究的是PowerShell範圍。我會更新我的答案。 –

+1

謝謝@ robert.westerlund。我認爲,點擊腳本可能是最接近我要得到的。 雖然看起來很奇怪 - 考慮到一個模塊被設計成可以從多個地方調用的代碼的重複使用,您可能會認爲有可能獲取腳本範圍變量。 感謝您的幫助。 – Dan

0

嘗試ContainsKey方法:

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

從模塊內部執行時,BoundParameters集合總是顯示爲空。 – Dan

+0

您是否將該命令放入函數中? –

0

在我的名爲.psm1,我把類似這樣的命令:

如果((GET-PSCallStack)[1] .Arguments樣「*放牧= True *'){Write-Host'導入此模塊的.ps1腳本是Verbose'};

您可以使用腳本塊在您的模塊範圍中設置變量,例如$ VerbosePreference,或者爲您自己的邏輯設置自己的唯一變量。

3

可以使用匹配的首選項變量和像這樣的語法傳遞大多數常用參數,-Parameter:$ParameterPreference。因此,對於詳細的特定情況,語法是-Verbose:$VerbosePreference

有幾個例外的:

  • 調試:中$DebugPreference值會自動被穿過,但指定-Debug開關強制$DebugPreferenceInquire
  • 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