Cómo utilizar correctamente los parámetros -verbose y -debug en cmdlet personalizada
-
29-09-2019 - |
Pregunta
Por defecto, cualquier función llamada que tiene el atributo [CmdletBinding ()] acepta (y otros pocos) -debug y -verbose parámetros y ha predefinido $ depurar y $ detallado variables. Lo que estoy tratando de averiguar es cómo pasarlos a otro cmdlet de que conseguir que llama dentro de la función.
Vamos a decir que tengo un cmdlet como esto:
function DoStuff() {
[CmdletBinding()]
PROCESS {
new-item Test -type Directory
}
}
Si -debug
o -verbose
se aprobó en mi función Quiero pasar esa bandera en el cmdlet new-item
. ¿Cuál es el patrón correcto para hacer esto?
Solución
Tal vez suene extraño, pero no hay manera fácil para un cmdlet para conocer su modo detallado o de depuración. Echar un vistazo a la pregunta relacionada:
¿Cómo sabe un cmdlet cuando se realmente debe llamar WriteVerbose ()?
Una opción no es perfecto, pero prácticamente razonable es introducir sus propios parámetros de cmdlet (por ejemplo $MyVerbose
, $MyDebug
) y utilizarlos en el código de forma explícita.
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 sólo necesitamos un interruptor (no, por ejemplo, el valor de nivel de detalle), entonces el enfoque con $PSBoundParameters
es quizás mejor que propuso por encima de los parámetros adicionales:
function DoStuff {
[CmdletBinding()]
param()
process {
if ($PSBoundParameters['Verbose']) {
# do verbose stuff
}
New-Item Test -Type Directory -Verbose:($PSBoundParameters['Verbose'] -eq $true)
}
}
DoStuff -Verbose
Se trata de todos modos no es perfecto. Si hay mejores soluciones entonces me gusta mucho a los conozco a mí mismo.
Otros consejos
$PSBoundParameters
no es lo que estás buscando. El uso del atributo [CmdletBinding()]
permite el uso de $PSCmdlet
dentro de su guión, además de proporcionar una bandera detallado. De hecho, es esta misma detallado que se supone que debes utilizar.
A través de [CmdletBinding()]
, puede acceder a los parámetros vinculados a través $PSCmdlet.MyInvocation.BoundParameters
. He aquí una función que utiliza CmdletBinding y simplemente entra en una pronta anidada inmediatamente con el fin de examinar las variables disponibles dentro del ámbito 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
Así que en su ejemplo, usted quiere lo siguiente:
function DoStuff `
{
[CmdletBinding()]
param ()
process
{
new-item Test -type Directory `
-Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true)
}
}
Esta tapas -Verbose, -Verbose: $ falsa, -Verbose:. $ True, y el caso en el interruptor no está presente en absoluto
No hay necesidad. PowerShell ya lo hace como el código de abajo demuestra.
function f { [cmdletbinding()]Param()
"f is called"
Write-Debug Debug
Write-Verbose Verbose
}
function g { [cmdletbinding()]Param()
"g is called"
f
}
g -Debug -Verbose
La salida es
g is called
f is called
DEBUG: Debug
VERBOSE: Verbose
No se hace lo más directo que pasa a la siguiente -Debug cmdlet sin embargo. Se realiza a través de las variables $ DebugPreference y $ VerbrosePreference. Escritura y depuración de escritura-detallado actúan como era de esperar, pero si quieres hacer algo diferente con la depuración o verbosa se puede leer aquí cómo comprobar por sí mismo.
Con un riesgo de reactivación y el hilo de edad. 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 va a repsect "-Verbose: $ falsa" o "-Debug: $ falsa". Sólo se fijará -Verbose / -Debug a $ cierto si se utiliza la siguiente:
DoStuff -Verbose
DoStuff -Verbose:$true
DoStuff -Debug
DoStuff -Debug:$true
Se puede construir una nueva tabla hash basado en la depuración encuadernado o verbosa parámetros y luego splat al comando interno. Si acaba de especificar los interruptores (y no está pasando un interruptor falsa, como $ depuración: $ falso) sólo se puede comprobar la existencia de depuración o verbosa:
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
}
}
La mejor manera de hacerlo es mediante el establecimiento de la $VerbosePreference
. Esto permitirá que el nivel de detalle de todo el guión. No se olvide que desactivarlo para el final de la secuencia de comandos.
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>>
}
Se puede configurar el VerbosePreference como una variable global sobre el inicio de la secuencia de comandos y para verificar si la variable global en su cmdlet personalizado.
Guión:
$global:VerbosePreference = $VerbosePreference
Your-CmdLet
Su-cmdlet:
if ($global:VerbosePreference -eq 'Continue') {
# verbose code
}
Comprobación de manera explícita en 'Continuar' permite que el guión sea igual a -verbose:$false
cuando se llama al cmdlet de un guión que no establece la variable global (en cuyo caso de $null
)
Creo que esta es la manera 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