Frage

In der Standardeinstellung jeder benannte Funktion, die das [CmdletBinding ()] Attribut akzeptiert debug und verbose (und einige andere) Parameter und hat $ debug und $ ausführliche Variablen vordefiniert. Was ich versuche, herauszufinden, wie sie die auf anderen Cmdlets passieren, dass die innerhalb der Funktion aufgerufen werden.

Lassen Sie uns sagen, ich habe ein Cmdlets wie folgt aus:

function DoStuff() {
   [CmdletBinding()]

   PROCESS {
      new-item Test -type Directory 
   }
}

Wenn -debug oder -verbose in meiner Funktion übergeben wurde möchte ich diese Fahne in das new-item Cmdlets zu übergeben. Was ist das richtige Muster, dies zu tun?

War es hilfreich?

Lösung

Vielleicht klingt es seltsam, aber es gibt keine einfache Möglichkeit für ein Cmdlet seines ausführlichen oder Debug-Modus zu kennen. Werfen Sie einen Blick auf die damit verbundene Frage:

Wie weiß ein Cmdlet, wenn es sollte wirklich WriteVerbose ()?

nennen

Eine nicht perfekt, aber praktisch vernünftige Option ist Ihre eigenen Cmdlets Parameter einzuführen (z $MyVerbose, $MyDebug) und sich im Code verwenden, explizit.

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 

UPDATE

Wenn wir brauchen nur ein Schalter (nicht etwa Ausführlichkeit Wert), dann der Ansatz mit $PSBoundParameters ist vielleicht besser als über zusätzliche Parameter vorgeschlagen:

function DoStuff {
    [CmdletBinding()]
    param()

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

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

DoStuff -Verbose

Es ist alles nicht perfekt sowieso. Wenn es bessere Lösungen gibt, dann würde ich wirklich, wie sie selbst kennen.

Andere Tipps

$PSBoundParameters ist nicht das, was Sie suchen. Die Verwendung des [CmdletBinding()] Attributs ermöglicht die Verwendung von $PSCmdlet in Ihrem Skript, zusätzlich zu einer Verbose Flagge bereitstellt. Es ist in der Tat das gleiche Verbose, dass Sie verwenden soll.

Durch [CmdletBinding()], können Sie die gebundenen Parameter durch $PSCmdlet.MyInvocation.BoundParameters zugreifen. Hier ist eine Funktion, das CmdletBinding verwendet und einfach in einem verschachtelten Prompt sofort, um die verfügbaren Variablen innerhalb der Funktion Umfangs zu untersuchen.

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                                                                                       

So in Ihrem Beispiel, würden Sie wie folgt vor:

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

Diese Abdeckungen -Verbose, -Verbose: $ false, -Verbose:. $ True, und der Fall, wo der Schalter überhaupt nicht vorhanden ist

Es ist nicht notwendig. Powershell bereits tut dies, da der Code unten zeigt.

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

Die Ausgabe ist

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

Es ist nicht so direkt getan, als ob -Debug zum nächsten Cmdlets übergeben. Es wird durch die $ DebugPreference und $ VerbrosePreference Variablen getan. Write-Debug und Write-Verbose handeln, wie man es erwarten würde, aber wenn Sie etwas anderes mit Debug tun wollen oder die ausführliche können Sie hier lesen: , wie für sich selbst überprüfen.

Mit einem Risiko von belebenden und alten Thread. Hier ist meine Lösung.

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
}

Was dies bedeutet unterscheidet sich von den anderen Beispielen ist, dass es repsect wird „-Verbose: $ false“ oder „-Debug: $ false“. Es wird nur dann gesetzt -Verbose / -Debug auf $ true, wenn Sie die folgende verwenden:

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

Sie können eine neue Hash-Tabelle auf dem gebundenen Debug oder ausführlichen Parameter basierend bauen und sie dann an den internen Befehl zu. Wenn Sie nur Schalter spezifizieren (und vorbei nicht einen falschen Schalter, wie $ debug: $ false) können Sie nur für die Existenz von Debug überprüfen oder ausführliche:

function DoStuff() { 
   [CmdletBinding()] 

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

Wenn Sie den Parameterwert übergeben es ist kompliziert, kann aber mit getan werden:

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

Der beste Weg, es zu tun ist durch die $VerbosePreference Einstellung. Dies wird die ausführliche Ebene für das gesamte Skript aktivieren. Vergessen Sie nicht, es bis zum Ende des Skripts zu deaktivieren.

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

Sie können die VerbosePreference als globale Variable auf Ihrem Skript starten und dann prüfen, für die globale Variable in Ihrem benutzerdefinierten Cmdlets.

Script:

$global:VerbosePreference = $VerbosePreference
Your-CmdLet

Ihr-CmdLet:

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

explizit Überprüfung auf ‚Weiter‘ ermöglicht das Skript gleich -verbose:$false zu sein, wenn Sie die CmdLet aus einem Skript aufrufen, die nicht die globale Variable nicht gesetzt (in diesem Fall ist es die $null)

Ich denke, das ist der einfachste Weg:

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top