sintaxis servicio scripts instrucciones consola comandos aprender powershell powershell-v2.0 cmdlets

servicio - ¿Cómo admite los parámetros-WhatIf y-Confirmación de PowerShell en un cmdlet que llama a otros cmdlets?



servicio de powershell (4)

Aquí hay una solución completa basada en las respuestas de @Rynant y @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) }

Tenemos que ver si -WhatIf se pasa por separado para que el whatif se pueda transmitir a los cmdlets individuales. ActualCmdletProcess es básicamente una refactorización para que no vuelva a llamar el mismo conjunto de comandos solo para el WhatIf . Espero que esto ayude a alguien.

Tengo un cmdlet de script de PowerShell que admite los parámetros -WhatIf & -Confirm .

Lo hace llamando al $PSCmdlet.ShouldProcess() antes de realizar el cambio.
Esto funciona como se esperaba.

El problema que tengo es que mi Cmdlet se implementa llamando a otros Cmdlets y los parámetros -WhatIf o -Confirm no se pasan a los Cmdlets que invoco.

¿Cómo puedo pasar los valores de -WhatIf y -Confirm a los Cmdlets que llamo desde mi Cmdlet?

Por ejemplo, si mi Cmdlet es Stop-CompanyXyzServices y usa Stop-Service para implementar su acción.

Si -WhatIf se pasa a Stop-CompanyXyzServices , quiero que también se pase a Stop-Service.

es posible?


Después de buscar en Google, encontré una buena solución para pasar parámetros comunes a los comandos llamados. Puede utilizar el operador @ splatting para pasar todos los parámetros que se pasaron a su comando. Por ejemplo, si

Servicio de inicio -Nombre ServiceAbc @PSBoundParameters

está en el cuerpo de su script. powershell pasará todos los parámetros que se pasaron a su script al comando Iniciar-Servicio. El único problema es que si la secuencia de comandos contiene un parámetro -Nombre, también se pasará y PowerShell se quejará de que incluyó el parámetro -Nombre dos veces. Escribí la siguiente función para copiar todos los parámetros comunes a un nuevo diccionario y luego lo escribí.

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

El resultado final es que pasa parámetros como -Verbose junto con los comandos llamados en su script y respetan la intención de las personas que llaman.


Actualizado por @manojlds comentario

Convierta $ WhatIf y $ Confirm a Boolean y pase los valores al cmdlet subyacente:

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


Pasando parámetros explícitamente

Puede pasar los parámetros -WhatIf y -Confirm con las $WhatIfPreference y $ConfirmPreference . El siguiente ejemplo logra esto con el parámetro splatting :

if($ConfirmPreference -eq ''Low'') {$conf = @{Confirm = $true}} StopService MyService -WhatIf:([bool]$WhatIfPreference.IsPresent) @conf

$WhatIfPreference.IsPresent será True si se usa el interruptor -WhatIf en la función que lo contiene. Al usar el interruptor -Confirm en la función que contiene, se establece temporalmente $ConfirmPreference a low .

Pasando parámetros implícitamente

Dado que las -Confirm y -WhatIf establecen temporalmente las variables $ConfirmPreference y $WhatIfPreference automática, ¿es incluso necesario pasarlas?

Considera el ejemplo:

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 da ShouldTestCaller resultado True desde ShouldProcess()

ShouldTestCaller -Confirm resulta en un mensaje de confirmación a pesar de que no pasé el interruptor.

Editar

La respuesta de @manojlds me hizo darme cuenta de que mi solución siempre estaba configurando $ConfirmPreference en ''Bajo'' o ''Alto''. He actualizado mi código para establecer solo el interruptor -Confirm si la preferencia de confirmación es ''Baja''.