Gültigkeitsbereich (Scope) von Variablen in PowerShell

    Kostenlose Studie: Was verdienen IT-Experten wirklich? Gliederung der Gehälter nach Berufserfahrung, Position und Funktion. Jetzt herunterladen »

    (Anzeige)

    Gültigkeits­bereiche von PowerShell-VariablenWie in den meisten fortgeschrittenen Script- und Program­mier­sprachen hängt die Verfügbarkeit von Variablen auch bei PowerShell vom jeweiligen Kontext ab. Eine unglückliche Wahl von Variablennamen kann daher im Zusammenspiel mit verschachtelten Gültigkeits­bereichen zu verwirrenden Ergebnissen führen.

    Das Konzept der Gültigkeits­bereiche trifft in PowerShell nicht nur auf Variablen zu, sondern auch auf Aliase, Funktionen und PowerShell Drives (wie etwa das Active-Directory-Laufwerk). Wenn man es jedoch im Zusammenhang mit Variablen verstanden hat, dann kann man es leicht auf die anderen Sprachelemente übertragen.

    Hierarchische Organisation

    Wenn man einer Variablen in einem Script zum ersten Mal einen Wert zuweist, dann ist sie nur dort verfügbar und nicht auf der Konsole, von der man das Script ausgeführt hat. Genauso wenig lässt sich der Wert einer Variablen auslesen oder verändern, wenn man sie in einer Funktion definiert hat und auf Script-Ebene auf sie zugreifen möchte. Verantwortlich dafür sind ihre Geltungsbereiche.

    Diese sind in einer hierarchischen Weise organisiert. Ganz oben ist der globale Gültigkeits­bereich angesiedelt. Er wird automatisch erzeugt, sobald man eine PowerShell-Sitzung startet. Direkt darunter findet sich der Gültigkeits­bereich für Scripts, gefolgt von Funktionen, die in einem Script definiert werden. Verschachtelt man Funktionen, dann erzeugt man für die inneren wieder einen eigenen Scope, der unter den äußeren liegt.

    Variablen, die in einem untergeordneten Gültigkeits­bereich definiert wurden, sind im übergeordneten nicht verfügbar. Umgekehrt kann man jedoch lesend auf Variablen zugreifen, die in einem übergeordneten Scope initialisiert wurden, und zwar bis hinab in die untersten Ebenen der Hierarchie.

    Es ist aber nicht möglich, eine Variable des übergeordneten Bereichs aus einem Code des untergeordneten Scopes zu verändern. Weist man dort einen Wert an eine Variable zu, die den gleichen Namen hat wie jene in einem darüber liegenden Bereich, dann erzeugt man eine neue Variable, die nur in diesem Bereich verfügbar ist. Alle Ebenen darunter verwenden nun diese Variable und nicht jene aus dem höheren Bereich.

    Legt man eine Variable auf der Konsole an, dann hat sie globale Gültigkeit. Den obigen Ausführungen zufolge kann man ihren Wert mithin auch in Scripts lesen. Ebenso sieht man eine Variable in einer Funktion, wenn man sie auf Script-Ebene erzeugt hat, ändern kann man sie allerdings dort nicht. Es ist möglich, eine Variable gleichen Namens im Script- und im function-Kontext zu erstellen, aber alle Ebenen unterhalb dieser Funktion werden dann ihre Variable und nicht jene des Scripts verwenden.

    Absolute versus relative Gültigkeitsbereiche

    Ein anderes wichtiges Konzept stellt der lokale Gültigkeits­bereich dar. Es handelt sich dabei nicht um das Gegenteil des globalen Scopes, vielmehr bezieht sich der Begriff immer auf den Kontext, in dem man die Variable erzeugt. Tut man dies zum Beispiel auf der PowerShell-Konsole, dann ist ihr lokaler Gültigkeits­bereich identisch mit dem globalen.

    Von Bedeutung ist der lokale Scope in Zusammenhang mit dem privaten Gültigkeits­bereich. Möchte man eine Variable explizit als privat deklarieren, dann ist sie nur in ihrem lokalen Scope verfügbar, aber nicht in untergeordneten Blöcken.

    Die Gültigkeits­bereiche Global, Local, Script und Private sind absolut, weil man sie über entsprechende Bezeichner direkt referenzieren kann. Daneben kann man sich auf Gültigkeits­bereiche auch relativ zum lokalen Scope beziehen. So hat Letzterer den Wert 0, der direkt übergeordnete hat den Wert 1, eine weitere Ebene höher spricht man mit 2 an, usw.

    Beispiel für Script vs. Funktion

    Folgende Beispiele sollen die Wirkungsweise von Scopes veranschaulichen. Wenn man sie in PowerShell ISE ausprobieren möchte, dann sollte man bedenken, dass sich dort alle Fenster einen Gültigkeits­bereich teilen und dies zu unerwarteten Ergebnissen führen wird. Daher ist es besser, die Beispiele auf der Konsole auszuführen.

    Das folgende Beispiel demonstriert die Hierarchie der Gültigkeits­bereiche:

    Änderungsversuche an Variablen aus dem Script-Bereich innerhalb einer Funktion bleiben wirkungslos.

    "Script scope" wird das erste Mal in der Funktion ausgegeben, wo Lesezugriff auf die Variable besteht, die am Anfang des Scripts definiert wurde, und das zweite Mal am Ende des Scripts. Das Zuweisen eines neuen Werts zur Variable $Script innerhalb der Funktion hatte somit keine Auswirkung auf Script-Ebene. Jedoch existiert nun innerhalb der Funktion eine neue Variable gleichen Namens und einem eigenen Wert. Die Variable $Function ist auf Script-Ebene nicht verfügbar und wird entsprechend dort auch nicht angezeigt.

    Standard-Scopes verändern

    Dieses Standardverhalten von PowerShell lässt sich durch eigene Scope-Bezeichner ändern. Sie beziehen sich auf die 4 absoluten Gültigkeits­bereiche Private, Local, Script und Global. Die folgende Anweisung erzeugt eine Variable mit einem privaten Scope, die in untergeordneten Bereichen nicht ansprechbar ist:

    $Private:myVariable = "Nur für den lokalen Bereich"

    Umgekehrt kann man eine Script-Variable für die ganze Session verfügbar machen, indem man sie als global deklariert. Dadurch verändert sich aber auch ihr lokaler Gültigkeits­bereich, also im eben genannten Fall auf global. Aus diesem Grund kann man nach Beendigung des Scripts auf der Konsole immer noch auf die Variable zugreifen, während alle Werte aus den anderen Scopes verloren gehen. Dieses Verhalten kann nützlich für die Fehlersuche sein.

    Das nächste Beispiel definiert zwei Variablen innerhalb der Funktion, aber erwartungsgemäß ist nur jene mit dem Bezeichner Script außerhalb verfügbar:

    Der Bezeichner Script sorgt dafür, dass Variablen aus der Funktion auch im Script zugänglich sind.

    Den Bezeichner local benötigt man in der Praxis kaum, weil er ohnehin nur den standardmäßigen Gültigkeits­bereich beschreibt, in dem eine Variable erzeugt wurde. Nachdem man diese Modifizierer aber nicht nur verwendet, um den Scope zu verändern, sondern auch um sich auf einen bestimmten zu beziehen, kann die Verwendung von local den Code verständlicher machen. Dazu ein Beispiel:

    Wenn man ältere oder einfachere Script-Sprachen gewohnt ist, dann zieht man es vielleicht vor, generell mit Variablen zu arbeiten, die im ganzen Script gelesen und verändert werden können. Dies entspricht natürlich nicht den Best Practices für PowerShell, aber mit dem Cmdlet Set-Variable lässt sich erreichen, dass alle untergeordneten Gültigkeits­bereiche vollen Zugriff erhalten.

    Wie man sieht, benötigen wir hier keinen der oben genannten Bezeichner. Vielmehr sorgt Set-Variable dafür, dass die Variable in allen untergeordneten Gültigkeits­bereichen gelesen und geschrieben werden kann. Alternativ kann man das Cmdlet New-Variable verwenden, um eine Variable zu definieren und dabei gleich die Eigenschaft AllScope zu vergeben:

    New-Variable -Name myVariable -Option AllScope -Value "Änderbar in allen untergeordneten Gültigkeits­bereichen"

    Möchte man zum Debuggen den Gültigkeits­bereich von allen Variablen, die im Script-Scope definiert wurden, auf global ausweiten, dann stellt man dem Aufruf des Scripts einen Punkt und ein Leerzeichen voran:

    . C:\Users\me\test.ps1

    Nach der Ausführung des Scripts stehen alle Variablen, die dort auf der obersten Ebene definiert wurden, auch in der Konsole zur Verfügung. Das gilt aber nicht für jene aus den Funktionen.

    2 Kommentare

    Bild von Raaja89
    Raaja89 sagt:
    19. September 2015 - 17:43

    Hallo,

    bei allem Respekt, dieser Artikel wurde von folgender Seite gestohlen:

    https://4sysops.com/archives/the-powershell-variable-scope/

    Bild von Wolfgang Sommergut
    19. September 2015 - 20:48

    Einfach einen Blick auf den Autor werfen, vielleicht kommt dann die Erleuchtung.