デフォルトでは、[CmdletBinding()]属性を持つ名前付き関数は、-debugおよび-verbose(および他のいくつかの)パラメーターを受け入れ、事前定義された$ debugおよび$ verbose変数を持ちます。私が理解しようとしているのは、関数内で呼び出される他のコマンドレットにそれらを渡す方法です。
次のようなコマンドレットがあるとします。
function DoStuff() {
[CmdletBinding()]
PROCESS {
new-item Test -type Directory
}
}
-debug
または-verbose
が関数に渡された場合、そのフラグをnew-item
コマンドレットに渡します。これを行うための正しいパターンは何ですか?
おそらく奇妙に聞こえるかもしれませんが、コマンドレットがその詳細モードまたはデバッグモードを知る簡単な方法はありません。関連する質問をご覧ください。
コマンドレットは、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
とにかく完璧ではありません。より良い解決策がある場合、私は本当に自分でそれらを知りたいです。
_$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、およびスイッチがまったく存在しない場合が含まれます。
必要はありません。 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 自分の確認方法を読むことができます。
古いスレッドを復活させるリスクがあります。これが私の解決策です。
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
それを行う最良の方法は、$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>>
}
バインドされたデバッグまたは冗長パラメータに基づいて新しいハッシュテーブルを作成し、それを内部コマンドにスプラットすることができます。スイッチを指定しているだけで($ 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
}
}
スクリプトの起動時にVerbosePreferenceをグローバル変数として設定し、カスタムコマンドレットでグローバル変数を確認できます。
スクリプト:
$global:VerbosePreference = $VerbosePreference
Your-CmdLet
Your-CmdLet:
if ($global:VerbosePreference -eq 'Continue') {
# verbose code
}
「続行」を明示的にチェックすると、スクリプトが-verbose:$false
グローバル変数を設定しないスクリプトからCmdLetを呼び出すとき(この場合は$null
)
これが最も簡単な方法だと思います:
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