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?

¿Fue útil?

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top