Parameter Binding-Konzepte in PowerShell

Inhaltsverzeichnis

Post Featured Image

Parameter Binding ist ein grundlegendes Konzept in PowerShell. Und es kann damit enden, dass man sich eine Weile am Kopf kratzt, wenn man dieses Konzept nicht vollständig versteht, wie ich kürzlich aus erster Hand erfahren habe.

In meinem Fall war es eine einfache Wiederholung fortgeschrittener Funktionen gefolgt vom Versuch, mit einem einfachen Script einen Taschenrechner zu generieren, um zu testen, an wie viel der Materie ich mich erinnern kann. Das Problem begann, als ich versuchte, Parameterwerte aus der Pipeline zu übermitteln.

In diesem Blog-Beitrag werde ich zwei grundlegende Konzepte zum Parameter Binding aus der PowerShell-Pipeline erläutern: „byValue“ und „byProperty“.

 

Lassen Sie uns meinen ersten Versuch mit meinem Taschenrechnerprogramm untersuchen. Wie Sie unten sehen können, handelt es sich dabei um ein einfaches PowerShell-Script zum Addieren, Subtrahieren, Multiplizieren und Dividieren zweier Zahlen (Abbildung 1a + 1b).

Screenshot: Calculator script. Name of Function: Get-Calculation; Three Parameters: firstNumber, secondNumber and Operator

Abbildung 1a: Einfaches Taschenrechner-Script Teil 1. Name der Funktion: Get-Calculation; drei Parameter: $firstNumber, $secondNumber und $operator. Parameter-Attribute: Mandatory und ValueFromPipeline. Der Operator-Parameter hat einen festen Satz von Werten.


Screenshot: Calculator script. Defining the output object and writing the output into the pipeline

Abbildung 1b: Einfacher Taschenrechner Teil 2. Definieren des Ausgabeobjekts und Schreiben des Ausgabeobjekts in die Pipeline.

 

Hier beginnt das Problem: Wenn ich versuche, ein benutzerdefiniertes Objekt mit den gleichen Eigenschaften wie meine Funktionsparameter zu erstellen und es an die Funktion Get-Calculation in der Pipeline zu übergebe, erhalte ich einen Fehler (Abbildung 3).

Screenshot: Passing a custom PS Object to Get-Calculation

Abbildung 3: Übergeben eines benutzerdefinierten PS-Objekts an Get-Calculation


       

Fehlersuche mit Trace-Command

Um das Problem weiter zu verstehen und zu beheben, beschloss ich, das Trace-Command cmdlet zu verwenden, um zu beobachten, wie das Parameter Binding in der Pipeline stattfindet. Ich führte den Befehl Trace-Command mit den folgenden Optionen aus, um das Parameter Binding zu beobachten „ParameterBinderBase, ParameterBinderController, ParameterBinding“. Der folgende Screenshot zeigt die Ausgabe von Trace-Command (Abbildung 4).

Screenshot: Using Trace-Command to examine parameter binding

Abbildung 4: Verwendung von Trace-Command zur Untersuchung des Parameter Binding

 

Wir können in Abbildung 5 beobachten, dass anstelle der Bindung von Objekteigenschaften an den Parameter das „ganze“ Objekt ($myObj) als Wert an den Parameter geliefert wird.

Screenshot: Parameter binding

Abbildung 5: Parameter Binding


       

Parameter Binding: byValue vs. byProperty

Dies geschieht, weil ich bei der Definition von Parameterattributen beschlossen habe, „ValueFromPipeline=$True“ zu setzen, was dazu führt, dass die Pipeline „byValue“ bindet.

„Bindung by Value“ bedeutet, dass das eingehende Objekt als Wert an den Parameter geliefert wird. Die Pipeline verarbeitet das Objekt nicht und bindet spezifische Eigenschaften des Objekts an Parameter für das nächste Cmdlet/die nächste Funktion in der Pipeline. Wenn wir die Ausgabe von Trace-Command beobachten, versucht die Pipeline, unser Objekt ({firstNumber=1; secondNumber=4; operator=+}) an den Parameter „firstNumber“ zu binden, und so weiter.

Die Lösung ist, „byProperty“ zu binden. In unserem Beispiel müssen wir der Pipeline explizit mitteilen, die Eigenschaften des eingehenden Objekts an unseren Parameter zu binden. Wie unten gezeigt, haben wir unser ursprüngliches Script geändert, um „byProperty“ zu binden (Abbildung 6).

Screenshot: Parameter attribute to accept value by propert

Abbildung 6: Parameter-Attribut, um „Value by property“ zu akzeptieren

 

Als Nächstes beobachten wir erneut das Verhalten unter Verwendung von Trace-Command. Wie wir diesmal sehen können, sind die Objekteigenschaften korrekt an unsere Parameter gebunden (Abbildung 7). Es gibt jedoch einen Haken: Damit dies funktioniert, sollten die Eigenschaften des eingehenden Objekts die gleichen Namen wie die Funktionsparameter haben.

Screenshot: Trace-Command reveals, parameter binding is successful

Abbildung 7: Erfolgreiches Parameter Binding


       

Test: Parameter Binding byValue und byProperty

In der nächsten Iteration desselben Scripts haben wir unsere Parameter so geändert, dass sie sowohl Parameter nach Wert als auch nach Eigenschaft akzeptieren (Abbildung 8). Zu Demonstrationszwecken habe ich beschlossen, den Operator-Parameter zu ändern, ihn non-mandatory zu machen, und ihm einen Standardwert von „+“ zuzuweisen.

Screenshot: Accepting parameter byValue and byProperty

Figure 8: Accepting parameter byValue and byProperty


 

Jetzt akzeptiert unsere Funktion Parameterwerte, indem sie sowohl die ByValue- als auch die ByProperty-Option verwendet. Nehmen wir ein einfaches Beispiel, bei dem wir zwei Objekte senden, eines vom Typ Int (Abbildung 9) und das andere ein benutzerdefiniertes PS Object (Abbildung 10).

Screenshot: Supplying two objects to Get-Valculation

bbildung 9: Übergabe von zwei Objekten an Get-Calculation


 

Das erste Ergebnis, bei dem wir 8 erhielten, mag etwas verwirrend sein, aber für das zweite Objekt funktionierte das Programm wie erwartet (Falls Sie sich über die Operator-Eigenschaft wundern, lasse ich es als Hausaufgabe für Sie hier).

Wir werden die Bindung mit unserem guten alten Freund, dem Trace-Befehl, beobachten. Wie Sie in Abbildung 10 sehen können, ist das erste Objekt, Nummer 4 vom Typ Int, an die erste Nummer und die zweite Nummer gebunden, was zu einer Summe von 8 führt. Dies zeigt, dass die Pipeline dasselbe Objekt mit allen Parametern verbindet, die einen Wert aus der Pipeline annehmen, wenn wir die Option „byValue“ verwenden.

Screenshot: Parameter binding for Int object

Abbildung 10: Parameter Binding für Int-Objekt


 

Im Fall unseres benutzerdefinierten PS Objects können wir beobachten, dass die Pipeline zunächst versucht, byValue zu binden, was jedoch fehlschlägt und dann erwartungsgemäß zur byProperty-Option wechselt und die Bindung der Parameter über den Eigenschaftsnamen beginnt (Abbildung 11).

Screenshot: Parameter binding for PS custom object

Abbildung 11: Parameter Binding für benutzerdefiniertes PS Object


       

Fazit

Die wichtigsten Punkte aus diesem Beitrag:

  1. Die Standardoption für die Parameterbindung ist die „binding by Value“.
  2. Wenn wir sowohl die Option ByValue als auch die Option ByProperty ausgewählt haben, beginnt die Pipeline mit der Bindung mit der Option ByValue.
  3. Wenn die Parameter direkt an die Funktion übergeben werden, dann wird der Prozessblock genau einmal ausgeführt.
  4. Wenn die Parameter per Pipeline geliefert werden, wird der Prozessblock für jedes Objekt in der Pipeline einmal ausgeführt.

Ich hoffe, dieser Beitrag hilft Ihnen, fortgeschrittene Funktionen besser zu verstehen und korrekt zu implementieren.

 

Zusammenhängende Posts

16 min read

ScriptRunner Portal Edition R4

4 min read

So nutzen Sie Azure Templates zur Automatisierung

Über den Autor: