Domanda

Per impostazione predefinita, qualsiasi funzione chiamata con l'attributo [CmdletBinding ()] accetta (altri e alcuni) -debug e -verbose parametri e ha predefiniti $ debug e $ verbose variabili. Quello che sto cercando di capire è come passare loro ad altri cmdlet di quella che vengono chiamato all'interno della funzione.

dire Let Ho un cmdlet in questo modo:

function DoStuff() {
   [CmdletBinding()]

   PROCESS {
      new-item Test -type Directory 
   }
}

se -debug o -verbose è stata approvata nella mia funzione voglio passare quella bandiera nella cmdlet new-item. Qual è il modello giusto per fare questo?

È stato utile?

Soluzione

Forse suona strano, ma non v'è alcun modo semplice per un cmdlet per conoscere la sua modalità dettagliata o di debug. Date un'occhiata alla relativa domanda:

Come si fa un cmdlet sapere quando in realtà dovrebbe chiamare WriteVerbose ()?

Una possibilità non perfetta ma praticamente ragionevole è quello di introdurre i propri parametri di cmdlet (ad esempio $MyVerbose, $MyDebug) e utilizzarli nel codice in modo esplicito.

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 

Aggiorna

Quando abbiamo bisogno solo di un interruttore (non, per esempio, il valore livello di dettaglio) allora l'approccio con $PSBoundParameters è forse meglio di quanto proposto al di sopra dei parametri aggiuntivi:

function DoStuff {
    [CmdletBinding()]
    param()

    process {
        if ($PSBoundParameters['Verbose']) {
            # do verbose stuff
        }

        New-Item Test -Type Directory -Verbose:($PSBoundParameters['Verbose'] -eq $true)
    }
}

DoStuff -Verbose

E 'tutto in ogni caso non è perfetto. Se ci sono soluzioni migliori, allora mi piacerebbe davvero sapere io stesso.

Altri suggerimenti

$PSBoundParameters non è quello che stai cercando. L'uso dell'attributo [CmdletBinding()] permette l'utilizzo di $PSCmdlet all'interno dello script, oltre a fornire una bandiera Verbose. E 'infatti questo stesso verbose che si suppone di utilizzare.

Attraverso [CmdletBinding()], è possibile accedere ai parametri legati attraverso $PSCmdlet.MyInvocation.BoundParameters. Ecco una funzione che utilizza CmdletBinding e semplicemente entra nested pronta immediatamente per esaminare le variabili disponibili all'interno della portata funzione.

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                                                                                       

Quindi nel tuo esempio, si vorrebbe il seguente:

function DoStuff `
{
    [CmdletBinding()]
    param ()
    process
    {
      new-item Test -type Directory `
        -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true)
    }
}

Questa cover -Verbose, -Verbose: $ false, -Verbose:. $ True, e il caso in cui l'interruttore non è presente a tutti

Non è necessario. PowerShell già fa questo come il codice qui sotto dimostra.

function f { [cmdletbinding()]Param()    
    "f is called"
    Write-Debug Debug
    Write-Verbose Verbose
}
function g { [cmdletbinding()]Param() 
    "g is called"
    f 
}
g -Debug -Verbose

L'uscita è

g is called
f is called
DEBUG: Debug
VERBOSE: Verbose

Non è fatto così diretto come passare -Debug al successivo cmdlet però. E 'fatto attraverso le variabili $ DebugPreference e $ VerbrosePreference. Write-Debug e Write-Verbose agire come ci si aspetterebbe, ma se si vuole fare qualcosa di diverso con debug o verbose potete leggere qui come controllare voi stessi.

Con il rischio di far rivivere e filo vecchio. Ecco la mia soluzione.

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
}

Quello che fa diverso dagli altri esempi è che sarà repsect "-Verbose: $ false" o "-Debug: $ false". Sarà solo impostare -Verbose / -Debug $ true se si utilizza il seguente:

DoStuff -Verbose
DoStuff -Verbose:$true
DoStuff -Debug
DoStuff -Debug:$true

Si potrebbe costruire una nuova tabella hash basato sul limite di debug o verbose parametri e poi splat al comando interno. Se sei solo specificando interruttori (e non sta passando un interruttore falso, come $ debug: $ false) si può solo verificare l'esistenza di debug o verbose:

function DoStuff() { 
   [CmdletBinding()] 

   PROCESS { 
        $HT=@{Verbose=$PSBoundParameters.ContainsKey'Verbose');Debug=$PSBoundParameters.ContainsKey('Debug')}
      new-item Test -type Directory @HT
   } 
} 

Se si desidera passare il valore del parametro E 'più complicato, ma può essere fatto 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 
   }  
}  

Il modo migliore per farlo è impostando la $VerbosePreference. Ciò consentirà il livello di dettaglio per l'intero script. Non dimenticate di disattivare entro la fine dello 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>>
   }

È possibile impostare il VerbosePreference come variabile globale su come avviare lo script e quindi controllare per la variabile globale nel cmdlet personalizzato.

Script:

$global:VerbosePreference = $VerbosePreference
Your-CmdLet

Il tuo-Cmdlet:

if ($global:VerbosePreference -eq 'Continue') {
   # verbose code
}

Controllo esplicitamente 'Continua' permette allo script di essere uguale a -verbose:$false quando si chiama il cmdlet da uno script che non impostare la variabile globale (nel qual caso del $null)

Credo che questo sia il modo più semplice:

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top