mandatory - powershell receive parameters
Cómo usar correctamente los parámetros-verbose y-debug en cmdlet personalizado (8)
Con riesgo de revivir y viejo hilo. Aquí está mi solución.
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
}
Lo que hace diferente de los otros ejemplos es que contendrá "-Verbose: $ false" o "-Debug: $ false". Solo establecerá -Verbose / -Debug en $ true si usa lo siguiente:
DoStuff -Verbose
DoStuff -Verbose:$true
DoStuff -Debug
DoStuff -Debug:$true
Por defecto, cualquier función nombrada que tenga el atributo [CmdletBinding ()] acepta los parámetros -debug y -verbose (y algunos otros) y tiene predefinidas las variables $ debug y $ verbose. Lo que estoy tratando de averiguar es cómo pasarlos a otros cmdlet que se llaman dentro de la función.
Digamos que tengo un cmdlet como este:
function DoStuff() {
[CmdletBinding()]
PROCESS {
new-item Test -type Directory
}
}
if -debug
or -debug
se pasó a mi función Quiero pasar ese indicador en el cmdlet de new-item
. ¿Cuál es el patrón correcto para hacer esto?
Creo que esta es la forma más fácil:
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
La mejor manera de hacerlo es configurando $VerbosePreference
. Esto habilitará el nivel detallado para todo el script. No olvide deshabilitarlo al final del script.
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>>
}
No hay necesidad. PowerShell ya lo hace como lo demuestra el siguiente código.
function f { [cmdletbinding()]Param()
"f is called"
Write-Debug Debug
Write-Verbose Verbose
}
function g { [cmdletbinding()]Param()
"g is called"
f
}
g -Debug -Verbose
El resultado es
g is called
f is called
DEBUG: Debug
VERBOSE: Verbose
No se hace tan directo como pasar -Debug al siguiente cmdlet sin embargo. Se realiza a través de las variables $ DebugPreference y $ VerbrosePreference. Write-Debug y Write-Verbose actúan como usted esperaría, pero si quiere hacer algo diferente con debug o verbose, puede leer here cómo verificarlo usted mismo.
Puede construir una nueva tabla hash basada en los parámetros de corrección de errores o detallados y luego colocarla en el comando interno. Si solo especifica switches (y no está pasando un interruptor falso, como $ debug: $ false), simplemente puede verificar la existencia de depuración o verbose:
function DoStuff() {
[CmdletBinding()]
PROCESS {
$HT=@{Verbose=$PSBoundParameters.ContainsKey''Verbose'');Debug=$PSBoundParameters.ContainsKey(''Debug'')}
new-item Test -type Directory @HT
}
}
Si desea pasar el valor del parámetro, es más complicado, pero se puede hacer con:
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
}
}
Puede establecer VerbosePreference como una variable global al iniciar el script y luego verificar la variable global en su cmdlet personalizado.
Guión:
$global:VerbosePreference = $VerbosePreference
Your-CmdLet
Your-CmdLet:
if ($global:VerbosePreference -eq ''Continue'') {
# verbose code
}
La comprobación explícita de ''Continuar'' permite que el guión sea igual a -verbose:$false
cuando se llama a CmdLet desde un guión que no establece la variable global (en cuyo caso es $null
)
Quizás suene extraño, pero no hay una manera fácil para que un cmdlet conozca su modo detallado o de depuración. Echa un vistazo a la pregunta relacionada:
¿Cómo sabe un cmdlet cuándo debería llamar realmente a WriteVerbose ()?
Una opción no perfecta pero prácticamente razonable es introducir sus propios parámetros de cmdlet (por ejemplo, $MyVerbose
, $MyDebug
) y usarlos explícitamente en el código.
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
ACTUALIZAR
Cuando solo necesitamos un conmutador (no, por ejemplo, un valor de nivel de verbosidad), entonces el enfoque con $PSBoundParameters
es tal vez mejor que los parámetros adicionales propuestos anteriormente:
function DoStuff {
[CmdletBinding()]
param()
process {
if ($PSBoundParameters[''Verbose'']) {
# do verbose stuff
}
New-Item Test -Type Directory -Verbose:($PSBoundParameters[''Verbose''] -eq $true)
}
}
DoStuff -Verbose
De todos modos, no es perfecto. Si hay mejores soluciones, me gustaría conocerlas yo mismo.
$PSBoundParameters
no es lo que estás buscando. El uso del [CmdletBinding()]
permite el uso de $PSCmdlet
dentro del script, además de proporcionar un indicador detallado. De hecho, es el mismo Verbose que se supone que debes usar.
A través de [CmdletBinding()]
, puede acceder a los parámetros enlazados a través de $PSCmdlet.MyInvocation.BoundParameters
. Aquí hay una función que usa CmdletBinding y simplemente ingresa una solicitud anidada inmediatamente para examinar las variables disponibles dentro del alcance de la función.
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
Entonces en tu ejemplo, querrías lo siguiente:
function DoStuff `
{
[CmdletBinding()]
param ()
process
{
new-item Test -type Directory `
-Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true)
}
}
Esto cubre -Verbose, -Verbose: $ false, -Verbose: $ true, y el caso donde el cambio no está presente en absoluto.