programing

다른 Cmdlet을 호출하는 Cmdlet에서 PowerShell의 -WhatIf & -Confirm 매개 변수를 어떻게 지원합니까?

muds 2023. 8. 19. 10:54
반응형

다른 Cmdlet을 호출하는 Cmdlet에서 PowerShell의 -WhatIf & -Confirm 매개 변수를 어떻게 지원합니까?

PowerShell 명령어를 지원하는 . 스크립트 cmdlet이 있습니다.-WhatIf&-Confirm매개 변수

전화를 통해 이 작업을 수행합니다.$PSCmdlet.ShouldProcess()메서드를 선택합니다.
이것은 예상대로 작동합니다.

는 내 과 Cmdlet을 입니다.-WhatIf또는-Confirm매개 변수는 호출하는 Cmdlet에 전달되지 않습니다.

의값을전면어해합니까야떻게려하달의 을 어떻게 할 수 ?-WhatIf그리고.-Confirm내 Cmdlet에서 호출하는 Cmdlet으로?

내 이 "cmdlet"인 Stop-CompanyXyzServices그리고 그것은 사용합니다.Stop-Service그 행동을 실행하기 위해.

한다면-WhatIf으로 전달됨Stop-CompanyXyzServices저는 그것을 Stop-Service에도 전달하기를 원합니다.

이것이 가능합니까?

매개 변수를 명시적으로 전달

당신은 통과할 수 있습니다.-WhatIf그리고.-Confirm가 " " " "인 경우:$WhatIfPreference그리고.$ConfirmPreference변수다음 예제에서는 매개 변수 분할을 사용하여 이를 수행합니다.

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

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

$WhatIfPreference.IsPresent▁▁be 될 것입니다.True-WhatIf스위치는 포함하는 기능에 사용됩니다. -Confirm 은 으로 설정합니다.$ConfirmPreferencelow.

암묵적으로 매개 변수 전달

-Confirm그리고.-WhatIf로 임로설니다합을 설정합니다.$ConfirmPreference그리고.$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

ShouldTestCaller으로 의결과가 됩니다.TrueShouldProcess()

ShouldTestCaller -Confirm스위치를 통과하지 못했는데도 확인 메시지가 표시됩니다.

편집

@manojlds 답변은 제 해결책이 항상 설정되어 있다는 것을 깨닫게 했습니다.$ConfirmPreference'낮음' 또는 '높음'으로 변경합니다.▁set▁only다▁to▁my니▁i▁updated▁have▁code습만 설정하도록 코드를 업데이트했습니다.-Confirm확인 기본 설정이 'Low'인 경우 스위치를 켭니다.

구글 검색을 통해 일반적인 매개 변수를 호출된 명령으로 전달할 수 있는 좋은 해결책을 찾았습니다.@ 분할 연산자를 사용하여 명령에 전달된 모든 매개 변수를 전달할 수 있습니다.예를 들어, 만약

Start-Service-Name Service Abc @PSBound 매개 변수

는 스크립트 powershell 본문에 있으며 스크립트에 전달된 모든 매개 변수를 Start-Service 명령으로 전달합니다.유일한 문제는 스크립트에 say -Name 매개 변수가 포함되어 있으면 스크립트도 전달되고 PowerShell이 -Name 매개 변수를 두 번 포함했다고 불평한다는 것입니다.모든 공통 파라미터를 새 사전에 복사하기 위해 다음 함수를 작성한 다음 분할합니다.

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와 같은 매개 변수를 스크립트에서 호출된 명령에 전달하면 호출자의 의도에 부합합니다.

다음은 @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가 개별 cmdlet에 전달될 수 있도록 별도로 전달됩니다.ActualCmdletProcess기본적으로 리팩터링이므로 동일한 명령 집합을 다시 호출하지 않습니다.WhatIf이것이 누군가에게 도움이 되기를 바랍니다.

@manojlds 주석별로 업데이트됨

$WhatIf 및 $Confirm을 Boolean으로 캐스팅하고 값을 기본 cmdlet에 전달합니다.

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)
        }                       
    }
}

이 질문과 답변에 몇 시간 동안 블록을 돌아다니지 않도록 대신 다음 기사를 읽어보시기를 제안합니다.

https://powershellexplained.com/2020-03-15-Powershell-shouldprocess-whatif-confirm-shouldcontinue-everything/ #combining-combining-combining-combin

여기에 제시된 답은 많은 경우에 효과적이지 않으며, 저는 근본적인 이해 없이 사람들이 여기서 답을 실행하는 것에 위험이 있다고 봅니다.

스크립트 모듈 간에 작동하도록 해킹한 방법은 다음과 같습니다.

언급URL : https://stackoverflow.com/questions/7180271/how-do-you-support-powershells-whatif-confirm-parameters-in-a-cmdlet-that-c

반응형