カスタムcmdletで-verboseおよび-debugパラメーターを適切に使用する方法
-
29-09-2019 - |
質問
デフォルトでは、[cmdletbinding()]属性を持つ名前のある関数は、-debugおよび-verbose(および他のいくつかの)パラメーターを受け入れ、事前に定義された$ debugおよび$ verbose変数を持っています。私が理解しようとしているのは、関数内で呼ばれる他のcmdletにそれらを渡す方法です。
私はこのようなcmdletを持っているとしましょう:
function DoStuff() {
[CmdletBinding()]
PROCESS {
new-item Test -type Directory
}
}
もしも -debug
また -verbose
私の関数に渡された私はそのフラグをに渡したい new-item
cmdlet。これを行うのに適したパターンは何ですか?
解決
おそらく奇妙に聞こえますが、CMDLETがその冗長モードまたはデバッグモードを知る簡単な方法はありません。関連する質問を見てください:
cmdletは、実際にWriteverbose()を呼び出す必要があることをどのようにして知るのですか?
完璧ではありませんが、実質的に合理的な選択肢の1つは、独自のcmdletパラメーターを導入することです(例: $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
アップデート
スイッチのみが必要な場合(たとえば、冗長レベルの値ではありません)、とのアプローチ $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()]
属性により、の使用が許可されます $PSCmdlet
冗長なフラグを提供することに加えて、スクリプト内で。実際、あなたが使用することになっているのはこれと同じ冗長です。
終えた [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
ただし、次のcmdletにdebugを通過するほど直接的に行われません。これは、$ debugpreferenceおよび$ verbrosepreference変数によって行われます。あなたが期待するように、書き込みbugと書き込みverboseの行為をしますが、デバッグや冗長性で何か違うことをしたい場合は読むことができます ここ 自分でチェックする方法。
復活のリスクと古いスレッド。これが私の解決策です。
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
バインドされたデバッグまたは冗長パラメーターに基づいて新しいハッシュテーブルを構築してから、内部コマンドにスプラットできます。スイッチを指定しているだけ($ debug:$ 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
. 。これにより、スクリプト全体の冗長レベルが可能になります。スクリプトの最後までに無効にすることを忘れないでください。
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>>
}
スクリプトを起動する際に、VerbosePreferenceをグローバル変数として設定し、カスタムCMDLetのグローバル変数を確認できます。
脚本:
$global:VerbosePreference = $VerbosePreference
Your-CmdLet
あなたの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