27

-WhatIf&-Confirmパラメーター をサポートする PowerShell スクリプト コマンドレットがあります。

これは$PSCmdlet.ShouldProcess()、変更を実行する前にメソッドを呼び出すことによって行われます。
これは期待どおりに機能します。

私が抱えている問題は、コマンドレットが他のコマンドレットを呼び出すことによって実装されており、-WhatIfまたは-Confirmパラメーターが呼び出したコマンドレットに渡されないことです。

コマンドレットから呼び出したコマンドレットの値を渡すにはどうすればよい-WhatIfですか?-Confirm

たとえば、私のコマンドレットがあり、そのアクションを実装するため Stop-CompanyXyzServicesに使用する場合。Stop-Service

-WhatIfが渡された場合はStop-CompanyXyzServices、Stop-Service にも渡されるようにします。

これは可能ですか?

4

6 に答える 6

19

パラメータを明示的に渡す

-WhatIfand-Confirmパラメータを$WhatIfPreferenceand変数で渡すことができ$ConfirmPreferenceます。次の例では、パラメーター splattingを使用してこれを実現しています。

if($ConfirmPreference -eq 'Low') {$conf = @{Confirm = $true}}

StopService MyService -WhatIf:([bool]$WhatIfPreference.IsPresent) @conf

$WhatIfPreference.IsPresentスイッチが含まれている関数で使用されているTrue場合になります。含まれている関数のスイッチを-WhatIf使用すると、一時的に に設定されます。-Confirm$ConfirmPreferencelow

パラメータを暗黙的に渡す

-Confirmandは-WhatIf一時的に$ConfirmPreferenceand変数を自動的に設定するので、$WhatIfPreferenceそれらを渡す必要さえありますか?

例を考えてみましょう:

function ShouldTestCallee {
    [cmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='Medium')] 
    param($test)

    $PSCmdlet.ShouldProcess($env:COMPUTERNAME,"Confirm?")
}


function ShouldTestCaller {
    [cmdletBinding(SupportsShouldProcess=$true)]
    param($test)

    ShouldTestCallee
}

$ConfirmPreference = 'High'
ShouldTestCaller
ShouldTestCaller -Confirm

ShouldTestCallerTrueからの結果ShouldProcess()

ShouldTestCaller -Confirmスイッチを渡さなかったにもかかわらず、確認プロンプトが表示されます。

編集

@manojldsの回答により、私のソリューションは常に$ConfirmPreference「低」または「高」に設定されていることに気付きました。-Confirm確認設定が「低」の場合にのみスイッチを設定するようにコードを更新しました。

于 2011-08-24T19:34:02.257 に答える
7

グーグルで調べた後、呼び出されたコマンドに共通のパラメーターを渡すための良い解決策を思いつきました。@ スプラッティング演算子を使用して、コマンドに渡されたすべてのパラメーターを渡すことができます。たとえば、

Start-Service -Name ServiceAbc @PSBoundParameters

はスクリプトの本文にあります。powershell は、スクリプトに渡されたすべてのパラメーターを Start-Service コマンドに渡します。唯一の問題は、スクリプトに -Name パラメーターが含まれている場合、それも渡され、PowerShell は -Name パラメーターが 2 回含まれていると文句を言うことです。次の関数を作成して、すべての共通パラメーターを新しい辞書にコピーし、それをスプラットしました。

function Select-BoundCommonParameters
{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        $BoundParameters
    )
    begin
    {
        $boundCommonParameters = New-Object -TypeName 'System.Collections.Generic.Dictionary[string, [Object]]'
    }
    process
    {
        $BoundParameters.GetEnumerator() |
            Where-Object { $_.Key -match 'Debug|ErrorAction|ErrorVariable|WarningAction|WarningVariable|Verbose' } |
            ForEach-Object { $boundCommonParameters.Add($_.Key, $_.Value) }

        $boundCommonParameters
    }
}

最終結果は、スクリプトで呼び出されるコマンドに -Verbose などのパラメーターを渡すことで、呼び出し元の意図を尊重します。

于 2011-11-03T18:29:19.387 に答える
3

@Rynant と @Shay Levy の回答に基づく完全なソリューションを次に示します。

function Stop-CompanyXyzServices
{
    [CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='Medium')]

    Param(
        [Parameter(
            Position=0,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true
        )]      
        [string]$Name
    )

    process
    {
        if($PSCmdlet.ShouldProcess($env:COMPUTERNAME,"Stop XYZ services '$Name'")){  
            ActualCmdletProcess
        }
        if([bool]$WhatIfPreference.IsPresent){
            ActualCmdletProcess
        }
    }
}

function ActualCmdletProcess{
# add here the actual logic of your cmdlet, and any call to other cmdlets
Stop-Service $name -WhatIf:([bool]$WhatIfPreference.IsPresent) -Confirm:("Low","Medium" -contains $ConfirmPreference)
}

-WhatIfwhatif を個々のコマンドレットに渡すことができるように、 if も個別に渡されることを確認する必要があります。ActualCmdletProcessは基本的にリファクタリングであるため、WhatIf. これが誰かに役立つことを願っています。

于 2011-08-24T18:26:54.963 に答える
1

@manojlds コメントごとに更新

$WhatIf と $Confirm をブール値にキャストし、その値を基になるコマンドレットに渡します。

function Stop-CompanyXyzServices
{
    [CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='High')]

    Param(
        [Parameter(
            Position=0,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true
        )]      
        [string]$Name
    )


    process
    {
        if($PSCmdlet.ShouldProcess($env:COMPUTERNAME,"Stop service '$Name'"))
        {                   
            Stop-Service $name -WhatIf:([bool]$WhatIf) -Confirm:([bool]$confirm)
        }                       
    }
}
于 2011-08-25T08:52:33.410 に答える