web-dev-qa-db-ja.com

カスタムコマンドレットで-verboseおよび-debugパラメーターを適切に使用する方法

デフォルトでは、[CmdletBinding()]属性を持つ名前付き関数は、-debugおよび-verbose(および他のいくつかの)パラメーターを受け入れ、事前定義された$ debugおよび$ verbose変数を持ちます。私が理解しようとしているのは、関数内で呼び出される他のコマンドレットにそれらを渡す方法です。

次のようなコマンドレットがあるとします。

function DoStuff() {
   [CmdletBinding()]

   PROCESS {
      new-item Test -type Directory 
   }
}

-debugまたは-verboseが関数に渡された場合、そのフラグをnew-itemコマンドレットに渡します。これを行うための正しいパターンは何ですか?

39
Micah

おそらく奇妙に聞こえるかもしれませんが、コマンドレットがその詳細モードまたはデバッグモードを知る簡単な方法はありません。関連する質問をご覧ください。

コマンドレットは、WriteVerbose()を実際に呼び出すタイミングをどのように知るのですか?

完璧ではありませんが、実際に合理的なオプションの1つは、独自のコマンドレットパラメーターを導入することです(例:$MyVerbose$MyDebug)およびコード内で明示的に使用します。

function DoStuff {
    [CmdletBinding()]
    param
    (
        # unfortunately, we cannot use Verbose name with CmdletBinding
        [switch]$MyVerbose
    )

    process {

        if ($MyVerbose) {
            # do verbose stuff
        }

        # pass $MyVerbose in the cmdlet explicitly
        New-Item Test -Type Directory -Verbose:$MyVerbose
    }
}

DoStuff -MyVerbose 

[〜#〜] update [〜#〜]

スイッチ(たとえば、冗長レベル値ではない)のみが必要な場合は、$PSBoundParametersは、おそらく上記の追加パラメーターよりも優れています。

function DoStuff {
    [CmdletBinding()]
    param()

    process {
        if ($PSBoundParameters['Verbose']) {
            # do verbose stuff
        }

        New-Item Test -Type Directory -Verbose:($PSBoundParameters['Verbose'] -eq $true)
    }
}

DoStuff -Verbose

とにかく完璧ではありません。より良い解決策がある場合、私は本当に自分でそれらを知りたいです。

32
Roman Kuzmin

_$PSBoundParameters_は探しているものではありません。 [CmdletBinding()]属性を使用すると、Verboseフラグを提供することに加えて、スクリプト内で_$PSCmdlet_を使用できます。実際には、これと同じVerboseを使用することになっています。

[CmdletBinding()]を介して、_$PSCmdlet.MyInvocation.BoundParameters_を介してバインドされたパラメーターにアクセスできます。 CmdletBindingを使用し、関数スコープ内で使用可能な変数を調べるために、ネストされたプロンプトをすぐに入力する関数を次に示します。

_PS D:\> function hi { [CmdletBinding()]param([string] $Salutation) $Host.EnterNestedPrompt() }; hi -Salutation Yo -Verbose

PS D:\>>> $PSBoundParameters

____________________________________________________________________________________________________
PS D:\>>> $PSCmdlet.MyInvocation.BoundParameters

Key Value                                                                                                                                                                                                           
--- -----                                                                                                                                                                                                           
Salutation Yo                                                                                                                                                                                                              
Verbose   True                                                                                       
_

したがって、あなたの例では、次のものが必要になります。

_function DoStuff `
{
    [CmdletBinding()]
    param ()
    process
    {
      new-item Test -type Directory `
        -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true)
    }
}
_

これには、-Verbose、-Verbose:$ false、-Verbose:$ true、およびスイッチがまったく存在しない場合が含まれます。

34
bwerks

必要はありません。 PowerShellは、以下のコードが証明するように、すでにこれを行っています。

function f { [cmdletbinding()]Param()    
    "f is called"
    Write-Debug Debug
    Write-Verbose Verbose
}
function g { [cmdletbinding()]Param() 
    "g is called"
    f 
}
g -Debug -Verbose

出力は

g is called
f is called
DEBUG: Debug
VERBOSE: Verbose

ただし、-Debugを次のコマンドレットに渡すほど直接的には行われません。これは、$ DebugPreferenceおよび$ VerbrosePreference変数を介して行われます。 Write-DebugとWrite-Verboseは期待どおりに動作しますが、debugまたはverboseで何か別のことをしたい場合は、 here 自分の確認方法を読むことができます。

26
Lars Truijens

古いスレッドを復活させるリスクがあります。これが私の解決策です。

function DoStuff {
    [CmdletBinding()]
    param ()

    BEGIN
    {
    $CMDOUT=@{
        Verbose=If ($PSBoundParameters.Verbose -eq $true) { $true } else { $false };
        Debug=If ($PSBoundParameters.Debug -eq $true) { $true } else { $false }
    }
    } # BEGIN ENDS

    PROCESS
    {
    New-Item Example -ItemType Directory @CMDOUT
    } # PROCESS ENDS

    END
    {
    } #END ENDS
}

これが他の例と異なる点は、「-Verbose:$ false」または「-Debug:$ false」を反映することです。以下を使用する場合にのみ-Verbose/-Debugを$ trueに設定します。

DoStuff -Verbose
DoStuff -Verbose:$true
DoStuff -Debug
DoStuff -Debug:$true
5
desek

それを行う最良の方法は、$VerbosePreference。これにより、スクリプト全体の詳細レベルが有効になります。スクリプトの最後までに無効にすることを忘れないでください。

Function test
{
  [CmdletBinding()]
   param( $param1)


  if($psBoundParameters['verbose'])
  {
     $VerbosePreference = "Continue"
     Write-verbose " Verbose mode is on"
   }
  else
   {
     $VerbosePreference = "SilentlyContinue"
     Write-verbose " Verbose mode is Off"
    }
   <<your code>>
   }
2
MilindK

バインドされたデバッグまたは冗長パラメータに基づいて新しいハッシュテーブルを作成し、それを内部コマンドにスプラットすることができます。スイッチを指定しているだけで($ debug:$ falseのようなfalseスイッチを渡していない場合)、デバッグまたは冗長の存在を確認するだけです。

function DoStuff() { 
   [CmdletBinding()] 

   PROCESS { 
        $HT=@{Verbose=$PSBoundParameters.ContainsKey'Verbose');Debug=$PSBoundParameters.ContainsKey('Debug')}
      new-item Test -type Directory @HT
   } 
} 

パラメータ値を渡したい場合はより複雑ですが、次の方法で実行できます。

function DoStuff {  
   [CmdletBinding()]  
   param()
   PROCESS {  
   $v,$d = $null
   if(!$PSBoundParameters.TryGetValue('Verbose',[ref]$v)){$v=$false}
   if(!$PSBoundParameters.TryGetValue('Debug',[ref]$d)){$d=$false}
   $HT=@{Verbose=$v;Debug=$d} 
   new-item Test -type Directory @HT 
   }  
}  
2
craika

スクリプトの起動時にVerbosePreferenceをグローバル変数として設定し、カスタムコマンドレットでグローバル変数を確認できます。

スクリプト:

$global:VerbosePreference = $VerbosePreference
Your-CmdLet

Your-CmdLet:

if ($global:VerbosePreference -eq 'Continue') {
   # verbose code
}

「続行」を明示的にチェックすると、スクリプトが-verbose:$falseグローバル変数を設定しないスクリプトからCmdLetを呼び出すとき(この場合は$null

1
svandragt

これが最も簡単な方法だと思います:

Function Test {
    [CmdletBinding()]
    Param (
        [parameter(Mandatory=$False)]
        [String]$Message
    )

    Write-Host "This is INFO message"

    if ($PSBoundParameters.debug) {
        Write-Host -fore cyan "This is DEBUG message"
    }

    if ($PSBoundParameters.verbose) {
        Write-Host -fore green "This is VERBOSE message"
    }

    ""
}
Test -Verbose -Debug
0
emekm