50

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

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

function DoStuff() {
   [CmdletBinding()]

   PROCESS {
      new-item Test -type Directory
   }
}

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

4

8 に答える 8

44

$PSBoundParametersあなたが探しているものではありません。この[CmdletBinding()]属性を使用$PSCmdletすると、Verbose フラグを提供するだけでなく、スクリプト内で を使用できます。実際、使用することになっているのは、これと同じ 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、およびスイッチがまったく存在しない場合が含まれます。

于 2011-07-20T19:51:21.187 に答える
38

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

コマンドレットは、実際に WriteVerbose() を呼び出す必要があるタイミングをどのように判断しますか?

完璧ではありませんが、実際には妥当なオプションの 1 つは、独自のコマンドレット パラメーター (たとえば、$MyVerboseand $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

アップデート

スイッチのみが必要な場合(たとえば、詳細レベルの値ではない) $PSBoundParameters、この回答の最初の部分で提案されている方法よりも(追加のパラメーターを使用して)アプローチする方がおそらく優れています。

function DoStuff {
    [CmdletBinding()]
    param()

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

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

DoStuff -Verbose

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

于 2010-11-29T08:49:48.667 に答える
28

必要はありません。以下のコードが証明するように、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 で別のことをしたい場合は、ここで自分で確認する方法を読むことができます。

于 2013-12-29T22:36:38.183 に答える
10

これが私の解決策です:

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
于 2013-04-30T10:22:18.713 に答える
3

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

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 
   }  
}  
于 2010-11-29T12:16:29.457 に答える
1

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

脚本:

$global:VerbosePreference = $VerbosePreference
Your-CmdLet

あなたのコマンドレット:

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

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

于 2015-08-27T10:00:48.290 に答える