Behandelte Themen unter "Die Variablen"

     0.  Einleitung

     1. benutzerdefinierte Variable
         Beispiel 1: verschiedene Typen von benutzerdefinierten Variablen
         Beispiel 2: Ein kleiner Blick hinter die Kulissen von Wertetypen wie Int32, Double oder Boolean
         1.1 implizite und explizite Typzuweisung
              1.1.1 implizite Typzuweisung
                       Beispiel 1: verschiedene initiale Typen von benutzerdefinierten Variablen
                       Beispiel 2: Implizite Typkonvertierung
              1.1.2 explizite Typzuweisung
                       Beispiel 1: Explizite Zuweisung von Variablen zu Typen
                       Beispiel 2: Umwandlung eines Arrays in einen String
                       Beispiel 3: Alphanumerische Zufallswerte erzeugen
         1.2 Typen von Variablen
               1.2.1 Strings
                        1.2.1.1 die .Net-Klasse [system.string]
                                    1.2.1.1.1 InstanzMethoden und InstanzEigenschaften der String-Klasse
                                                   Beispiel 1: Anzeige der InstanzEigenschaften und InstanzMethoden von [System.String]
                                                   Beispiel 2a: Beginn und Ende eines Strings vergleichen
                                                   Beispiel 2b: Umwandlung in Groß- und Kleinbuchstaben
                                                   Beispiel 2c: Länge eines Strings bestimmen
                                   1.2.1.1.2 statische Eigenschaften und Methoden der String-Klasse
                                                  Beispiel 1: Anzeige der statischen Methoden und Eigenschaften von [System.String]
                                                  Beispiel 2a: Ist eine Variable Empty oder Null?
                                                  Beispiel 2b: Vergleich zweier Strings
                                   1.2.1.1.3 Konstruktoren der String-Klasse
                                                  Beispiel 1: verschiedene Konstruktoren der Klasse [System.String]
                       1.2.1.2 Expandingstrings, Escapecharakter, Literalstrings
                                  Beispiel 1: Expanding String mit einer Variable, einem Ausdruck und Sonderzeichen mit EscapeCharacter
                                  Beispiel 2: Maskieren mit dem EscapeCharakter (=Backtick) und Zeilenumbruch im Code
                                  Beispiel 3: Literalstrings
                      1.2.1.3 Multiline Strings (Here Strings)
                                  Beispiel 1: Definition eines Multilinestrings
                                  Beispiel 2: Auskommentieren einer längeren Passage im Code
             1.2.2 Int32 / Double / Boolean
                      Beispiel 1: Eigenschaften von Int32
                      Beispiel 2: Eigenschaften von Double
                      Beispiel 3: Eigenschaften von Boolean
             1.2.3 Skriptblocks
                      Beispiel 1a: Definition einer ScriptBlock-Variable
                      Beispiel 1b: Methoden einer Skriptblock-Variablen
                      Beispiel 1c: Ausführen eines Skriptblock-Variablen mit dem Call-Operator
                      Beispiel 1d: Eine For-Schleife und eine If-Bedingung mit je einem Skriptblock
                      Beispiel 2: Parameterübergabe in einen Skriptblock
                      Beispiel 3: Parametrisieung des Powershell-Codes
              
     2. Preference Variables und CommonParameter
         2.1 Preference Variables
               Beispiel 1: $OFS (Output Field Separator)
               Beispiel 2: erlaubte Anzahl an Variablen
               Beispiel 3: Bestimmen der aktuell verwendeten Zahl von Variablen
               Beispiel 4: Bestimmen der aktuellen Anzahl der Aliase
         2.2 Common Parameters
               2.2.1 Verbose  (PreferenceVariable: $VerbosePreference)
                        Beispiel 1: Ausgabe von Verbosemeldungen
                       
Beispiel 2: Einsatz von Write-Verbose mit dem Commonparameter "Verbose"
               2.2.2
Debug (PreferenceVariable: $DebugPreference)
               2.2.3 Erroraction (PreferenceVariable: $ErrorActionPreference)
                        Beispiel 1a: Unterdrücken von Errormeldungen ohne Abbruch des Skripts für einen Befehl (- Erroraction SilentlyContinue oder -EA 0).
                       
Beispiel 1b: Unterdrücken von Errormeldungen ohne Abbruch des Skripts skriptweit (- Erroraction SilentlyContinue)
                       
Beispiel 2: Ausgabe der ersten Errormeldung mit Abbruch des Skripts (-ErrorAction Stop oder –EA 1)
                        Beispiel 3: Ausgabe der Errormeldungen ohne Abbruch des Skripts (-ErrorAction Continue oder –EA 2)
                        Beispiel 4: Unterbrechung des Skripts mit Rückfrage beim User  (-ErrorAction Inquire oder –EA 3)
               2.2.4
Errorvariable
                        Beispiel 1: Errormessages in einer Errorvariablen speichern
               2.2.5
WarningAction (PreferenceVariable: $WarningPreference)
                        Beispiel 1: Warnungen und ihre Folgen
               2.2.6 WarningVariable
                        Beispiel 1: Warnungen und ihre Folgen
               2.2.7 Outvariable
                       
Beispiel 1: Ausgabe auf den Bildschirm und gleichzeitig in eine Variable
               2.2.8
OutBuffer

      3. automatic Variables

 ******************************************************************************************************

 

0 Einleitung

Powershell unterscheidet nach diesem Technetartikel  about_Variables drei verschiedene Variablentypen.

1) benutzerdefinierte Variablen
Das sind vom Programmierer erstellte Variable, die nach dem Beenden der Powershell aus dem Speicher gelöscht werden.

$zahl=5
$text="Powershell"


2) Preference Variables und CommonParameter
Die Preference Variables wirken sich auf das Verhalten eines Powershellskripts insgesamt aus. Beispielsweise ob bei Fehlern im Skript abgebrochen, eine Warnung ausgegeben oder still weitergemacht werden soll. Mit den Commonparametern kann man das Verhalten sogar einzelner Anweisungen des Skripts abweichend von den Preference Variables beeinflussen.

Technet:  about_preference_variables (Deutsch: Einstellungsvariablen)
Technet:  about_commonparameters

 http://technet.microsoft.com/de-de/library/dd315352.aspx


3) Automatic Variables
dabei handelt es um etwa 50 Variablen, die Powershell mitbringt und auf die wir Anwender nur lesenden Zugriff haben. Diese Variablen können sich innerhalb eines Skript und sogar innerhalb einer Befehlszeile verändern. Einige dieser Variablen sind es, die die Powershell so mächtig machen wie beispielsweise die Variable "$_".
"$_" ist die Grundlage für das Pipelining der Powershell, das in fast jedem Powershellskript vorkommt.
Auch andere Automatischen Variablen tauchen neben "$_" immer wieder in Beispielskripten auf, sind dort aber nicht immer erklärt. Ein Blick in die Liste dieses Variablentyps hilft dann weiter.

Technet:  about_Automatic Variables


Zusätzlich zu den drei genannten Variablentypen, möchte ich als vierten Typ die Umgebungsvariablen oder "Environment Variables" nennen. Auf diese Variablen bin ich im Kapitel Filesystem -> 1.1.1.2 Umgebungsvariablen - Environment Variables näher eingegangen, weswegen ich hier nur den Link dazu setze. Dieses Kapitel oder den Hilfeartikel in der Technet:  about_Environment_Variables sollte man sich auf jeden Fall mal ansehen, da die Umgebungsvariablen immer wieder auftauchen.

 

1 benutzerdefinierte Variable

Benutzerdefinierte Variablen sind immer Objekte mit bestimmten Eigenschaften und Methoden. Diese Eigenschaften sind abhängig von den Klassen, von denen die Objekte abgeleitet wurden.

Variablen können

- einfache Wertetypen [System.ValueTypes] wie Integer, Double oder Boolean (auch Literale genannt)
- StringObjekte
- Arrays [system.array]
- Scriptblocks
- Hashtables [system.object]
- WMI-Objekte [System.Management.ManagementBaseObject]
- .Net-Objekte aller Art 
sein.
ALLE diese Variablen sind Objekte, was unter VBS noch nicht durchgängig der Fall war.


1.1 implizite und explizite Typzuweisung

MSDN:  Übersicht über die einfachen Typen von Variablen

Bei der Verwendung von Variablen übernimmt Powershell die korrekte Zuweisung von Varaiblen zu passenden Klassen meist selbst. Sollte sich herausstellen, daß die gewählte Klasse im Laufe des Programmablaufs doch nicht die richtige war, so versucht Powershell die Variable in eine andere Klasse automatisch so zu konvertieren, daß keine Informationen verloren gehen.
Meist muß sich der Programmierer um nichts kümmern.

Ich habe bewusst eben zweimal das Wörtchen "meist" verwendet. Trifft der Fall zu und der Programmierer muß tatsächlich nicht eingreifen, so spricht man von einer "impliziten Typzuweisung".

Powershell bietet natürlich auch die Möglichkeit an, Variable von Beginn an selbst einer Klasse zuzuweisen oder ein in einen gewünschten Typ zu konvertieren (= casten). Dann spricht man von einer "expliziten Typzuweisung"

Beide Arten der Typzuweisung beschreibe ich in den nächsten beiden Unterkapiteln


1.1.1 implizite Typzuweisung

In der Powershell müssen Variablen vor ihrer Verwendung nicht deklariert werden. Powershell weist einer neuen Variable implizit einer (meist) passenden Klasse zu. Im folgenden Beispiel 1 sind dazu einige Beispiel aufglistet.

Beispiel 1: verschiedene initiale Typen von benutzerdefinierten Variablen

In den folgenden Beispielen weise ich Variablen verschiedene Werte zu und frage anschliessend den Variablentyp ab. In 99% der Fälle passt der von Powershell ausgewählte Variablentyp.

remove-variable a -ErrorAction silentlycontinue #damit keine Missverständnisse durch eventuelle Vorbelegungen dieser Variablen auftreten
$a=2 #WertObjekt der Klasse Int32
$a.gettype() | Format-Table Name,BaseType -auto

#Ausgabe

Name  BaseType       
----  --------       
Int32 System.ValueType

 

remove-variable b -ErrorAction silentlycontinue#damit keine Missverständnisse durch eventuelle Vorbelegungen dieser Variablen auftreten
$b=5.5   #WertObjekt der Klasse Double
$b.gettype() | Format-Table Name,BaseType -auto

#Ausgabe

Name   BaseType       
----   --------       
Double System.ValueType

 

remove-variable c -ErrorAction silentlycontinue #damit keine Missverständnisse durch eventuelle Vorbelegungen dieser Variablen auftreten
$c=(4 -lt 6)   #Objekt der Klasse Boolean
$c.gettype() | Format-Table Name,BaseType -auto

#Ausgabe

Name    BaseType       
----    --------       
Boolean System.ValueType

 

remove-variable d -ErrorAction silentlycontinue #damit keine Missverständnisse durch eventuelle Vorbelegungen dieser Variablen auftreten
$d="hello"   #Objekt der Klasse String
$d.gettype() | Format-Table Name,BaseType -auto

#Ausgabe

Name   BaseType    
----   --------    
String System.Object

 

remove-variable e -ErrorAction silentlycontinue #damit keine Missverständnisse durch eventuelle Vorbelegungen dieser Variablen auftreten
$e=1,2,6,9    #System.Array-Objekt
$e.gettype() | Format-Table Name,BaseType -auto

#Ausgabe

Name     BaseType   
----     --------   
Object[] System.Array

 

remove-variable f -EA 0 #damit keine Missverständnisse durch eventuelle Vorbelegungen dieser Variablen auftreten
$f=@{Projektleiter="Karl Napf";TechnischerRedakteur="Heinz Kunz"}   #Hashtabelle
$f.gettype() | Format-Table Name,BaseType -auto

#Ausgabe

Name      BaseType    
----      --------    
Hashtable System.Object

 

remove-variable g -EA 0 #damit keine Missverständnisse durch eventuelle Vorbelegungen dieser Variablen auftreten
$g=get-wmiobject win32_bios   #Managementobjekt oder WMIObjekt
$g.gettype() | Format-Table Name,BaseType -auto

#Ausgabe

Name             BaseType                             
----             --------                             
ManagementObject System.Management.ManagementBaseObject

 

remove-variable h -EA 0 #damit keine Missverständnisse durch eventuelle Vorbelegungen dieser Variablen auftreten
$h=([io.directoryinfo]"C:\")   #.Net-Objekt der Klasse DirectoryInfo
$h.gettype() | Format-Table Name,BaseType -auto

#Ausgabe

Name          BaseType               
----          --------               
DirectoryInfo System.IO.FileSystemInfo

 

remove-variable i -EA 0 #damit keine Missverständnisse durch eventuelle Vorbelegungen dieser Variablen auftreten
$i = [system.Enum]::GetValues([System.Environment+SpecialFolder]) | #System Array
$i.gettype() | Format-Table Name,BaseType -auto

#Ausgabe
Name            BaseType   
----            --------   
SpecialFolder[] System.Array

 

Beispiel 2: Implizite Typkonvertierung

Remove-variable a -EA 0
$a=6 #WertObjekt der Klasse Int32
$a.gettype() | Format-Table Name,BaseType -auto
$a=$a+0.5
$a.gettype() | Format-Table Name,BaseType -auto

##Ausgabe

Name  BaseType       
----  --------       
Int32 System.ValueType


Name   BaseType       
----   --------       
Double System.ValueType

Die Variablenzuweisung "$a=6" interpretiert Powershell default als ein Objekt der Klasse Int32 mit einem ganzzahligen Wertebereich von etwa -2 Milliarden bis +2 Milliarden. Für viele Situationen ist dies die passende Wahl. Sollte später mal die Variable einen Nachkommaanteil erhalten "$a=$a+0.5", so wandelt Powershell $a automatisch in ein Objekt der Klasse Double um.

remove-variable b -ErrorAction silentlycontinue
$b=6 #WertObjekt der Klasse Int32
$b.gettype() | Format-Table Name,BaseType -auto
#[int32]::maxvalue #2147483647
$b=$b+2147483647
$b.gettype() | Format-Table Name,BaseType -auto

#Ausgabe

Name  BaseType       
----  --------       
Int32 System.ValueType


Name   BaseType       
----   --------       
Double System.ValueType

Die Variablenzuweisung "$a=6" interpretiert Powershell default als ein Objekt der Klasse Int32 mit einem ganzzahligen Wertebereich von etwa -2 Milliarden bis +2 Milliarden. Für viele Situationen ist dies die passende Wahl. Sollte später mal die Variable den Wertebereich von [Int32]  übersteigen", so wandelt Powershell $a automatisch in ein Objekt der Klasse Double um.

Remove-variable c -EA 0
[int16]$b=6 #WertObjekt der Klasse Int32
$c.gettype() | Format-Table Name,BaseType -auto
[int16]::maxvalue  # 32767
$c=$c+32767

#Ausgabe

Cannot convert value "32773" to type "System.Int16". Error: "Der Wert für einen Int16 war zu groß oder zu klein."
At line:20 char:3
+ $c <<<< =$c+32767
    + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

Daß die implizite Typumwandlung nicht immer funktioniert, zeigt dieses Beispiel einer Variable vom Typ [Int16]. Läßt man deren Wert über den Maimalwert steigen, so erhält man einen Fehler. Offenbar haben die Powershellentwickler den Typ [Int32] im Gegensatz zu anderern Typen mit besonderen Schutzmechanismen ausgestattet
Wenn kein trifftiger Grund vorliegt, würde ich ganze Zahlen im Defaulttyp [Int32] speichern. In Zeiten von 64-Bit Betriebssystemen dürfte die Speicherersparnis durch den Einsatz kleinerer Typen bei Skripten kaum eine Rolle mehr spielen. 

 

1.1.2 explizite Typzuweisung

Natürlich kann man auch eine Variable einer bestimmten Klasse zuweisen (casten) oder eine bereits mit einem Wert gefüllte Variable in eine andere Klasse konvertieren, sofern Powershell dies als möglich erachtet.

MSDN:  Übersicht über die .NET Framework-Klassenbibliothek


Beispiel 1: Explizite Zuweisung von Variablen zu Typen

remove-variable a
[int32]$a=7
$a.gettype() | Format-Table Name,BaseType -auto
$a=[int64]$a
$a.gettype() | Format-Table Name,BaseType -auto
$a
$a=[int32]$a
$a.gettype() | Format-Table Name,BaseType -auto
$a

#Ausgabe

Name  BaseType       
----  --------       
Int32 System.ValueType


Name  BaseType       
----  --------       
Int64 System.ValueType

7

Name  BaseType       
----  --------       
Int32 System.ValueType

7

Anmerkung: Die Variable a wird ohne Wertverlust von [Int32] nach [Int64] und auch wieder zurück konvertiert


Beispiel 2: Umwandlung eines Arrays in einen String

$a=@()     #a ist als Array definiert. Die Elemente können beliebige Typen haben
 #[string[]]$a  $a ist als Array definiert, dessen Elemente nur Strings sein dürfen

$a="Karl"," ","Napf"
"Ausgabe als Array"
$a

"`nAusgabe als umgewandelten String"
[string]$a

#Ausgabe

Ausgabe als Array
Karl
 
Napf

Ausgabe als umgewandelten String
Karl Napf

 Technet:  about_Arrays


Beispiel 3: Alphanumerische Zufallswerte erzeugen

Hier ein etwas praxisnäheres Beispiel:

Function get-alphanumericRandom{
   param($digits=8,[string]$flag='111', $SpaceFrequency=4,[boolean]$LineFeed=$false)
   $RandomPool=$null

   $flag=[Convert]::ToInt32($flag, 2)

   $min_lower=[int][char]'a' #97
   $max_lower=[int][char]'z' #122

   $min_upper=[int][char]'A'  #65
   $max_upper=[int][char]'Z'  #90

   $min_number=[int][char]'0' #48
   $max_number=[int][char]'9' #57

   $space =[int][char]' ' #32

   if($flag -band 1){
     $randompool=[char[]]($min_lower..$max_lower)
   }
 
   if($flag -band 2){
     $randompool+=[char[]]($min_upper..$max_upper)
   }
 
   if($flag -band 4){
     $randompool+=[char[]]($min_number..$max_Number)
     }

   if($flag -band 8){
     for($i=1;$i -le $spaceFrequency;$i++){
       $randompool +=" "
     } #for
   }
 
 
   #Benutzerdefinierte zusätzliche Zeichenketten
   for($i=1;$i -le 3;$i++){
       $randompool +="Karl"
   }
   for($i=1;$i -le 2;$i++){
       #if($linebreak){$randompool +="`n"} #Zeilenumbruch
       if($linefeed){$randompool +=[Environment]::NewLine}
     }

  $ofs = ''

  [string](get-random -input $randompool -count $digits)
}#function Ende

#BeispielAufruf
get-alphanumericRandom -digits 10 -flag 1111

#Ausgabe

y5C DBWtw4


Dieses Beispiel ist mir beim Schreiben des Kapitels Filesystem eingefallen. Dort habe ich den Bedarf für eine kleine Testumgebung einige Ordner und Dateien mit zufälligen Namen und Inhalten zu erstellen.
Das cmdlet Get-Random  Technet: Get-Random liefert entweder nur Zufallszahlen zwischen einem Minimalwert und einem Maximalwert zurück, oder aber man gibt dem cmdlet eine Collection in Form eines Arrays mit, aus dem beim Aufruf eine bestimmte Anzahl an Elementen zufällig ausgewählt wird. Als Array könnte man "A","a","B" ... übergeben, aber das wäre doch etwas zu unelegant.

Anwendungsbeschreibung der Funktion get-AlphanumericRandom:

Die obige Funktion hat drei (optionale) Parameter und kann auch innerhalb des Codes noch etwas angepasst werden
 a) digits (Default 8): gibt an, aus wievielen Zeichen der Zufallsstring bestehen soll
 b) flag (default '0111'): ein vierstelliger binärer Flag mit folgendem Aufbau:
        - die erste (niedrigste) Stelle beschreibt, ob im Zufallsstring Kleinbuchstaben vorkommen sollen
        - die zweite Stelle beschreibt, ob im Zufallsstring Großbuchstaben vorkommen sollen
        - die dritte Stelle beschreibt, ob im Zufallsstring Zahlen vorkommen sollen
        - die vierte Stelle beschreibt, ob im Zufallsstring Leerzeichen vorkommen sollen
c) SpaceFrequency (Default 4): steuert, mit welcher Wahrscheinlichkeit Leerzeichen im Zufallstring vorkommen. Je höher, desto wahrscheinlicher

Durch diese Parameter, sowie die Möglichkeit im Funktionscode eigene Strings und Charakter für das InputArray eingeben zu können, eignet sich die Funktion ganz gut, um  zufällige Datei- und Ordnernamen zu erzeugen, aber auch zum erstellen von längeren Textdateien.
Beides benötige ich wiegesagt, um etwas Testmaterial für das Kapitel Filesystem zu bekommen. Auch die Erzeugung einigermaßen zufälliger Passwörter wäre ein möglicher Einsatz dieser Funktion.

       

1.2 Typen von Variablen

Im vorangegangenen Kapitel 1.1 Implizite und Explizite Typzuweisung haben wir gesehen, dass ein Powershellprogrammierer sich eher selten um die Typen seiner verwendeten Variablen Gedanken machen muß.

Trotzdem gibt es ein paar interessante Punkte zu den wichtigsten Variablentypen zu sagen, deren Kenntnis zum Verständnis ganz bestimmt nicht schadet.
Daher verzichte ich in diesem Kapitel auf Vollständigkeit im Bezug auf alle Typen und beschränke mich auf die Typen [System.String], [System.Int32], [System.Double],  [System.Boolean], sowie [System.Management.Automation.ScriptBlock]

1.2.1 Strings

Strings sind natürlich wieder Objekte, die aus der zugehörigen .Net-Klasse [System.String] erstellt werden. Kaum ein Skript kommt ohne Strings aus.

Dieses Unterkapitel dreht sich um die Stringklasse mit ihren Methoden, Eigenschaften und Konstruktoren ansich. Das Auffinden bestimmter Patterns oder die Manipulation von Strings innerhalb von Texten behandle ich im Kapitel "Textmanipulationen und Reguläre Ausdrücke"

Strings haben in der Powershell einige Besonderheiten, wie die einfachen und doppelten Anführungszeichen (Literal und Expandingstring), den Escapecharacter (`)und die Multilinestrings. Diese Punkte möchte ich neben der Klassenbeschreibung im Folgenden behandeln.

 

1.2.1.1 die .Net Klasse [system.string]

MSDN:  String-Klasse (System)

Wie schon erwähnt, möchte ich mich in diesem Kapitel "Die Variablen" nicht zu sehr auf Textmanipulationen eingehen, sondern eher den Schwerpunkt auf das Thema "Strings als einer von mehreren Variablentypen" setzen und nur einen Überblick über die Klasse [System.String] geben mit nur ein paar Beispielen.

Im Kapitel "Textmanipulationen und Reguläre Ausdrücke" werde ich tiefer auf die "Analyse und Manipulation von Strings" eingehen.

1.2.1.1.1 InstanzMethoden und InstanzEigenschaften der String-Klasse

Beispiel 1: Anzeige der InstanzEigenschaften und InstanzMethoden von [System.String]

$a = "Napf"
#Gleichbedeutend mit
$a=[system.string]"Napf"

$a | gm

#Ausgabe gekürzt

TypeName: System.StringNamhttps://www.powershellpraxis.de/typo3/backend.phpe             MemberType            Definition
----             ----------            ----------
StartsWith       Method                bool StartsWith(string value), bool StartsWith(string valu

ToUpper          Method                System.String ToUpper(), System.Stri

Length           Property              System.Int32 Length {get;}

Es ist Geschmackssache ob man sich die InstanzMethoden und -Eigenschaften auf diese Weise ausliest, oder in in der MSDN nachsieht: MSDN:  String-Klasse (System). In den Tabellen "Eigenschaften" und "Methoden" sind diejenigen auf Instanzen anwendbar, die kein rotes "S" für "Static" links stehen haben.



Beispiel 2a: Beginn und Ende eines Strings vergleichen

Für die Methoden und Eigenschaften der Stringklasse, die wir uns in Beispiel 1 angesehen haben, ein paar kleine Beispiele

[system.string]$a="KarlNapf"  #die explizite Typeangabe ist natürlich nicht notwendig und hat nur nochmal verdeutlichenden Charakter
$a.startswith("Karl")
$a.endswith("Erwin")

#Ausgabe

True
False

 

Beispiel 2b: Umwandlung in Groß- und Kleinbuchstaben

$a="KarlNapf"
$a.ToUpper()

#Ausgabe

KARLNAPF

 

Beispiel 2c: Länge eines Strings bestimmen

$a="KarlNapf"
$a.Length

#Ausgabe

8

 

1.2.1.1.2 statische Eigenschaften und Methoden der String-Klasse

Statische Methoden und Eigenschaften werden direkt auf die Klasse angewandt werden. Die Stringklasse hat hiervon ein paar sehr nützliche im Gepäck

Beispiel 1: Anzeige der statischen Methoden und Eigenschaften von [System.String]

[string] | get-member -static


   TypeName: System.String

Name            MemberType Definition
----            ---------- ----------
Compare         Method     static int Compare(string strA, string strB), s
CompareOrdinal  Method     static int CompareOrdinal(string strA, string s
Concat          Method     static string Concat(System.Object arg0), stati
Copy            Method     static string Copy(string str)
Equals          Method     static bool Equals(string a, string b), static
Format          Method     static string Format(string format, System.Obje
Intern          Method     static string Intern(string str)
IsInterned      Method     static string IsInterned(string str)
IsNullOrEmpty   Method     static bool IsNullOrEmpty(string value)
Join            Method     static string Join(string separator, string[] v
ReferenceEquals Method     static bool ReferenceEquals(System.Object objA,
Empty           Property   static System.String Empty {get;}

Es ist Geschmackssache ob man sich die statischen Methoden und -Eigenschaften auf diese Weise ausliest, oder in in der MSDN nachsieht:
MSDN:  String-Klasse (System). In den Tabellen "Eigenschaften" und "Methoden" sind diejenigen statisch, die ein rotes "S" für "Static" links stehen haben.

 

Für die Methoden und Eigenschaften der Stringklasse, die wir uns in Beispiel 1 angesehen haben, ein paar kleine Beispiele

Beispiel 2a: Ist eine Variable Empty oder Null?

MSDN:  String.IsNullOrEmpty-Methode

$a=5
[string]::isnullorempty($a)

remove-variable a  # identisch zu $a=$null
[string]::isnullorempty($a)

#Ausgabe

False
True

Der Unterschied zwischen einer leeren Variablen und einer Variablen mit dem Wert $null ist durchaus wichtig und kann bei Nichtbeachten unangenehme Fehler verursachen.
Möchte man Userkonten aus dem Activedirectory herausfiltern, die keine Beschreibung haben, so möchte man meist sowohl Konten erkennen, deren Beschreiubngsfeld noch nie (=$Null) belegt war, wie auch Konten deren Beschreibung (=$Empty) gelöscht wurde. 


Beispiel 2b: Vergleich zweier Strings

$a="KarlNapf"
$b="KarlNapf"

[string]::Compare($a, $b, $True)

#Ausgabe

0

Über die MSDN  String.Compare-Methode (String, String, Boolean) erfährt man über die möglichen Rückgabewerte dieser statischen Methode

Kleiner als 0  - strA ist kleiner als strB.
0 (null)           - strA ist gleich strB.
Größer als 0   - strA ist größer als strB.



1.2.1.1.3 Konstruktoren der String-Klasse

Konstruktoren sind ebenos Elemente einer .Net Klasse wie Eigenschaften oder Methoden. Konstruktoren erzeugen beim Aufruf einer Klasse mit dem cmdlet new-object eine Instanz, also ein Objekt aus einer Klasse.
Eine Klasse kann -meistens hat sie das auch- mehrere Konstruktoren besitzen, die sich durch Art und Anzahl der zu übergebenden Parameter unterscheiden. Klassen mit mehr als einem Konstruktor nennt man "überladen". Je nachdem, welchen Konstruktor man verwendet, erhält man ein etwas anderes Objekt.
Die verschiedenen Konstruktoren einer .Net Klasse kann man sich in der MSDN in der Klassenbeschreibung ansehen.


Beispiel 1: verschiedene Konstruktoren der Klasse [System.String]

Mit get-member erhält man, wie iim voran gegangenen Kapitel gezeigt, schon eine ganze Reihe von Möglichkeiten zurück, was man mit Strings über statische und nichtstatitische Methoden und Eigenschaften anstellen kann.
Es gibt noch weitere Anwendungsmöglichkeiten über die Konstruktoren, die nur durch einen Blick auf die Klassenbeschreibung in der Technet ersichtlich sind MSDN:  String-Klasse (System). Die verschiedenen Konstruktoren der Stringklasse sind durch get-member nicht ersichtlich.


MSDN:  String-Konstruktor (Char*, Int32, Int32)

Angabe des ersten Zeichens(5) und der Länge(4) 

$a = new-object System.string("Karl_Napf",5,4)
$a

#Ausgabe

Napf

 

MSDN:  String-Konstruktor (Char, Int32)

Wiederholung eines Unicode-Zeichens ("K"), so of wie angegeben (5)

$a = new-object System.string("K",5)
$a

#Ausgabe

KKKKK

Auch dieses Beispiel hat wieder eher verdeutlichenden Charakter. In der Praxis würde man meistens einen String wohl eher durch eine Anweisung wie $a=5*"K" vervielfachen, was dann auch bei Strings mit mehr als einem Zeichen funktioniert.

$a = "KarlNapf"*5
$a

#Ausgabe

KarlNapfKarlNapfKarlNapfKarlNapfKarlNapf

 

MSDN:  String-Konstruktor (Char*)

$a = new-object system.string("KarlNapf")
$a -is [System.String]

#Ausgabe

True

$a= new-object system.string("KarlNapf") wird jeder in der Praxis natürlich mit $a="KarlNapf" abkürzen

 

1.2.1.2 Expandingstrings, Escapecharakter, Literalstrings

Technet:  about_Quoting_Rules

Zeichenfolgen werden in Powershellskripten entweder in einfache oder doppelte Anführungszeichen gesetzt.

Doppelte Anführungszeichen bewirken, daß in einem String
   - Variablen durch ihre Werte ersetzt werden "Der Wert ist $i" -> "Der Wert ist 5"
   - Ausdrücke ausgewertet werden "Der Wert ist $(2+3)" -> "Der Wert ist 5"
   - Sonderzeichen mit dem Escape_Character umgesetzt werden "Der Wert  ist:`t 5" -> "Der Wert ist      5"

Man spricht von einem Expanding String

Beispiel 1: Expanding String mit einer Variable, einem Ausdruck und Sonderzeichen mit EscapeCharacter

$var="KarlNapf"
$a="User `t`t $env:username `nOS `t`t $env:OS `nVar `t`t$var `nAusdruck`t`t$(2+3)"
$a

#Ausgabe

User          j184710
OS          Windows_NT
Var         KarlNapf
Ausdruck        5

Anmerkung 1: die Sonderzeichen `t und `n stehen für  “horizontal tab” und “new line”.  siehe Escapecharacter im nächsten Beispiel

Anmerkung 2: Es werden die zwei Umgebungsvariablen username und OS verwendet. Umgebungsvariaben siehe  Filesystem -> 1.1.1.2 Umgebungsvariablen - Environment Variables

Anmerkung 3: Wenn die Ausgabe vernünftig formatiert sein soll, seht euch das Kapitel Formatierung des Outputs an.

Der Escapecharakter leitet einige Sonderzeichen der Powershell ein, die in der Technet unter  Technet: about_Escape_Characters aufgelistet sind.

          `0  Null
`a Benachrichtigung
`b Rückschritt
`f Seitenvorschub
`n Zeilenwechsel
`r Wagenrücklauf
`t Horizontaler Tabstopp
`v Vertikaler Tabstopp


Der Escapecharakter hat noch zwei weitere Funktionen in der Powershell. Zum einen maskiert er in einem Expanding String eine Variable, wodurch diese nicht ersetzt wird, zum anderen zeigt er in einem Skript an, daß der Befehl in der nächsten Zeile des Codes weitergeschrieben wird. Der Escapecharakter wird außerhalb der Powershell auch häufiger als Backtick bezeichnet

Beispiel 2: Maskieren mit dem EscapeCharakter (=Backtick) und Zeilenumbruch im Code

$a=5
"Die Variable `$a soll nicht ersetzt werden, außerdem ist `
   diese Codezeile erst hier fertig"

#Ausgabe

Die Variable $a soll nicht ersetzt werden, außerdem ist
  diese Codezeile erst hier fertig

Ohne den Backtick vor $a wäre die Variable a durch ihren Wert 5 ersetzt worden und ohne den Backtick am Ende der zweiten Zeile hätte es eine Fehlermeldung gegeben.


Beispiel 3: Literalstrings

$a=5
'Die Variable $a soll nicht ersetzt werden, was in "Literalstrings" sowieso nicht geschieht'

#Ausgabe

Die Variable $a soll nicht ersetzt werden, was in "Literalstrings" sowieso nicht geschieht.

Literalstrings sind Strings in einfachen Anführungszeichen. In diesen Strings werden keine Ersetzungen vorgenommen, dafür können Sonderzeichen wie doppelte Anführungszeichen ohne Maskierung eingebaut werden. Weitere Beispiele, wie man Anführungszeichen in Strings einbaut, findet ihr in dem oben schon angebenen Technet Artikel  about_Quoting_Rules

 

1.2.1.3 Multiline Strings (Here Strings)

Ein Multiline- oder Herestring ist intern ein normaler String der Klasse [System.String]. Powershell macht uns mit diesen Strings nur das Leben bei der Definition längerer Zeichenketten, die sich über mehrere Zeilen hinziehen können, einfacher.

Beispiel 1: Definition eines Multilinestrings

$a =@"
Erste Zeile
Zweite Zeile
Dritte Zeile
"@

$a
$a.Length
$a.gettype() | Format-Table Name,BaseType -auto

#Ausgabe

Erste Zeile
Zweite Zeile
Dritte Zeile
39

Name   BaseType     
----   --------     
String System.Object


Here-Strings können mehrere Zeilen umfassen und werden mit @" und "@ ( expanding String) bzw  @‘ und ‘@ (literal string) begrenzt. Beide Begrenzungen müssen in einer eigenen, vom eigentlichen String getrennten Zeile stehen.

Here-Strings sind normale Strings [System.String], auf die alle .Net-Methoden und Eigenschaften der String-Klasse angewendet werden können. Here-Strings werden beim Verfassen größerer Texte, z.B. für die OnlineHilfe eines Skriptes, eingesetzt. 


Beispiel 2: Auskommentieren einer längeren Passage im Code

Ebenfalls nützlich sind Here-Strings zum schnellen Auskommentieren grösserer Skriptpassagen. Dann allerdings sollte man Powershell durch die Variable $null mitteilen, dass der String nicht gespeichert werden braucht

$null=@"  #$null speichert nichts, $a würde den ganzen Here-String zwischenspeichern
Hier beginnt ein langer Kommentar
..
Hier endet ein langer Kommentar
"@


1.2.2. Int32 / Double / Boolean

Interessante Informationen der Klasse [system.Int32] erhält man über die statischen Eigenschaften dieser Klasse

Beispiel 1: Eigenschaften von Int32

[system.int32] | gm -static

#Ausgabe

   TypeName: System.Int32

Name            MemberType Definition  
----            ---------- ---------- 
MaxValue        Property   static System.Int32 MaxValue {get;}
MinValue        Property   static System.Int32 MinValue {get;}                                                                         

 Mit diesen Informationen lässt sich der Wertebereich einer Int32 Variablen anzeigen

[int32]::MinValue
[system.int32]::MaxValue

#Ausgabe

-2147483648
2147483647

Dieser Wertebereich ist für die meisten Anwendungen sicher ausreichend. Beim Skripten besteht glaube ich nur selten die Notwendigkeit auf kleinere Typen zum Einsparen von Speicherplatz auszuweichen.

 

Beispiel 2: Eigenschaften von Double

[double]::MinValue
[system.double]::MaxValue

#Ausgabe

-1,79769313486232E+308
1,79769313486232E+308

Double hat einen Wertebereich von einer negativen Zahl -17 mit 307 Nullen dahinter, bis zu einer positiven Zahl +17 mit 307 Nullen dahinter. Mir ist nicht bekannt, ob irgendeine reale Größe diesen Wertebereich ausschöpft, vielleicht sowas wie Atome im Weltall


Beispiel 3: Eigenschaften von Boolean

[boolean] | gm -static   TypeName: System.Boolean

#Ausgabe gekürzt

Name            MemberType Definition                                                                                                                            
----            ---------- ----------                                                                                                                            
...
FalseString     Property   static System.String FalseString {get;}                                                                                               
TrueString      Property   static System.String TrueString {get;}         

Mit diesen Informationen lassen sich die Werte für Wahr und Falsch anzeigen

[boolean]::TrueString
[boolean]::FalseString

#Ausgabe

True
False

 

1.2.3 Skriptblocks

Skriptblocks sind aus Sicht des Programmierers ein Mittelding zwischen Funktionen und Variablen. Einer Variable werden Anweisungen zugewiesen, die an beliebiger Stelle beliebig oft aufgerufen werden können. Der VariablenTyp ist tatsächlich "Skriptblock" und nicht wie bei Funktionen entweder ein Array oder ein ValueType (abhängig von der Return-Anweisung in der Funktion)
Ein Skriptblock ist der rechte Teil einer For-Schleife oder einer If-Bedingung, der zwischen den geschweiften Klammern steht (siehe Beispiel 1d)


Beispiel 1a: Definition einer ScriptBlock-Variable 

$ScriptBlock={
 $a=8
 $b=7
 "{0} + {1} = {2}" -f $a,$b,$($a+$b)
}

"Inhalt der Variable Scriptblock: $Scriptblock"

"Typ der Variable Scriptblock: $($ScriptBlock.GetType().Name)"

#Ausgabe

Inhalt der Variable Scriptblock:
 $a=8
 $b=7
 "{0} + {1} = {2}" -f $a,$b,$($a+$b)

Typ der Variable Scriptblock: ScriptBlock

Die Variable Scriptblock enthält also tatsächlich Code, der aber in diesem Beispiel noch nicht ausgeführt wird. Dies kann durch den Einsatz des CallOperators "&$ScriptBlock" oder über die Methode Invoke "$ScriptBlock.Invoke()" geschehen, wie in den nachfolgenden Beispielen gezeigt wird.


Beispiel 1b: Methoden einer Skriptblock-Variablen

$ScriptBlock={
 $a=8
 $b=7
 "{0} + {1} = {2}" -f $a,$b,$($a+$b)
}
"`nEigenschaften und Methoden eines Skriptblocks"
$ScriptBlock | Get-Member

#Ausgabe gekürzt

  TypeName: System.Management.Automation.ScriptBlock

Name                 MemberType Definition  
----                 ---------- ----------  
GetType              Method     type GetType()                
Invoke               Method     System.Collections.ObjectModel.Collection[psobject]               
InvokeReturnAsIs     Method     System.Object InvokeReturnAsIs(Params System.Object[] args)       
ToString             Method     string ToString()

Die Methoden GetType() und ToString() sind in jeder Klasse dabei und nichts Besonderes. Die beiden Methoden Invoke() und InvokeReturnAsIs() sind dagegen etwas interessanter, wie die nachfolgenden Beispiele zeigen werden

MSDN:  ScriptBlock-Methods


Beispiel 1c: Ausführen eines Skriptblock-Variablen mit dem Call-Operator

$ScriptBlock={GET-WMIObject Win32_Bios}
$(&$ScriptBlock).BiosVersion  # "&" ist der sogenannte "Call"-Operator

#mögliche Ausgabe

A M I  - 10000602
BIOS Date: 10/02/06 17:12:27 Ver: 08.00.12
BIOS Date: 10/02/06 17:12:27 Ver: 08.00.12

Technet:  about_Operators  -> Call Operator

Durch Anwendung des CallOperators wird in diesem Beispiel der Code der ScriptBlock-Variablen "&" ausgeführt.


Beispiel 1d: Eine For-Schleife und eine If-Bedingung mit je einem Skriptblock

$ScriptBlock={$i}
For($i=1;$i -lt 3; $i+=1){&$ScriptBlock}

$ScriptBlock={"`nHallo Karl"}
if(2 -gt 1){&$ScriptBlock}

#Ausgabe
1
2

Hallo Karl


In einem Skriptblock kann auch längerer Code verarbeitet werden. Man kann beispielsweise den Code aus Beispiel 1a unter 3.2 Tabellen aus formatierten Strings erstellen zwischen die beiden geschweiften Klammern des Skriptblocks setzen und kann den Skriptblock mit den gezeigten Möglichkeiten aufrufen.

 
Beispiel 2: Parameterübergabe in einen Skriptblock

MSDN:  ScriptBlock.Invoke-Method

MSDN:  ScriptBlock.InvokeReturnAsIs - Method

Laut MSDN ist die Methode InvokeReturnAsIs() effizienter.

$ScriptBlock={
 $Args[0]
 Get-WMIObject Win32_Bios -Computername $Args[0]
}
 
$ReturnValue = $ScriptBlock.Invoke("PC1")
$ReturnValue

#mögliche Ausgabe

SMBIOSBIOSVersion : 0701  
Manufacturer      : American Megatrends Inc.
Name              : BIOS Date: 10/02/06 17:12:27 Ver: 08.00.12
SerialNumber      : System Serial Number
Version           : A M I  - 10000602

Die übergebenen Parameter sind innerhalb des SkriptBlocks als Elemente des Arrays $args ansprechbar.

Übergibt man nur wenige Parameter und braucht nur einen einzigen Rückgabewert, so sind Skriptblocks den Funktionen sehr ähnlich.

Technet:  about_Functions

Technet:  about_Functions_Advanced


Beispiel 3: Parametrisieung des Powershell-Codes

Etwas "verrückt" ist die Möglichkeit, selbst den eigentlichen PS-Code parametrisieren zu können. Ob es für dieses Beispiel einen praktischen Einsatz gibt, weiß ich nicht. Ich finds dennoch geil :-)

$ScriptBlock={
 Get-WMIObject Win32_$($args[0])
}

$Arguments=@("Bios","Service","Process")
$Arguments | foreach{
 $($ScriptBlock.Invoke($_))
 }

In diesem Beispiel werden also die WMI-Klassen Win32_Bios, Win32_Service und Win32_Process nacheinander aufgerufen.
args[0] komplettiert bei jedem Durchlauf die Befehlszeile "Get-WMIObject Win32_"

 

2 Preference Variables und CommonParameter

2.1 Preference Variables

Mit den sogenannte "preference variables" werden grundsätzliche Powershellparameter wie die maximale Anzahl (Variable: $MaximumVariableCount) oder das Verhalten bei Fehlern im Skript (Variable: $ErrorActionPreference") definiert.

In der Powershellhilfe in den "conceptual help topics" oder in der Technet unter  about_preference_variables findet sich eine umfangreiche Hilfe. Neben vielen anderen nützlichen Informationen findet man hier auch die Defaultwerte der "preference variables"

get-help about_preference_variables

#gekürzte Ausgabe

The following table lists the preference variables and their default
values.

Variable                             Value
--------                             -----
$ConfirmPreference                   High
$DebugPreference                     SilentlyContinue
$ErrorActionPreference               Continue

$MaximumHistoryCount                 64
$MaximumVariableCount                4096
$OFS                                 (Space character (" "))

$WarningPreference                   Continue
$WhatIfPreference                    0
$WsmanMaxRedirectionCount            5

Eine Preference Variable wirkt immer auf das gesamte Skript. Einige "preference variables" können allerdings durch einen Common Parameter, die im nächsten Kapitel beschrieben werden, für einen Befehl oder cmdlet-Aufruf überschrieben werden.

Man kann den Wert einer "preference variables" durch eine einfache Zuweisung überschreiben, wie im folgenden Beispiel gezeigt,


Beispiel 1: $OFS (Output Field Separator)

$OFS hat default den Space character (" "). Der Preference Parameter $OFS wird benutzt wird, sobald ein Feld als String ausgegeben wird.

$array="test1","test2","test3"
[string]$array

#Ausgabe
test1 test2 test3


$OFS wird zu
"+++"

$OFS="+++"
$array="test1","test2","test3"
[string]$array

#Ausgabe
test1+++test2+++test3

 
Löschen von OFS (default)

Remove-Variable OFS
#Beachte: OFS nicht $OFS

Die PreferenceVariable $OFS gilt, wie üblich bei Variablen, nur für die aktuelle Powershellsession. Will man die $OFS in jeder PowershellSession setzen, so muss dies in der Profildatei geschehen


Beispiel 2: erlaubte Anzahl an Variablen

Interessant sind auch die Maximum…Parameter, die bestimmen, wieviele Aliase oder Variablen in einer Session erlaubt sind. Zu den Variablen werden alle Variablen aus dem laufenden Skript, aus den Profilskripten und auch die PreferenceVariables gezählt

get-help about_preference_variables

#gekürzte Ausgabe der default values (fast am Anfang der OnlineHilfe)

….
$MaximumAliasCount                   4096
$MaximumDriveCount                   4096
$MaximumErrorCount                   256
$MaximumFunctionCount                4096
$MaximumHistoryCount                 64
$MaximumVariableCount                4096

 

Beispiel 3: Bestimmen der aktuell verwendeten Zahl von Variablen

(get-variable).count

#Ausgabe
60

 

Beispiel 4: Bestimmen der aktuellen Anzahl der Aliase

(get-alias).count

#Ausgabe
138


Ansich sind alle PreferenceVariables Wert behandelt zu werden. Da in dem bereits erwähnten "Conceptual help topic" about_preferencevariables die Preference Variablen ausführlich besprochen werden, erspare ich mir hier weitere Details und erwähne nur die Parameter, die sich mit den CommonParameters überschneiden wie beispielsweise das Errorhandling.

2.2 CommonParameter

 Technet: about_commonparameters

Möchte man eine über eine "preference variable" definierten Eigenschaft der Powershell nur für einen Befehl ändern, so nimmt man dazu den passenden CommonParameter. Dieser CommonParameter wird als Option an das cmdlet angehängt und gilt dann nur für diesen Befehl.

Bei Aufruf der Onlinehilfe eines cmdlets mit der Option "-detailed" werden die von diesem cmdlet supporteten commonparameters im Parameterblock angezeigt. Nicht jeder Commonparameter muss belegt sein

get-help get-process -detailed

#gekürzte Ausgabe
SYNTAX
Get-Process [-ComputerName <string[]>] ... [<CommonParameters>]

#und am Ende der Parameterliste im Detail
PARAMETERS

<CommonParameters>
This cmdlet supports the common parameters: -Verbose, -Debug,
    -ErrorAction, -ErrorVariable, -WarningAction, -WarningVariable,
    -OutBuffer and -OutVariable. For more information, type,
    "get-help about_commonparameters".

 

Bei den Commonparameters handelt es sich um die folgenden acht Parameter, sowie zwei weitere Parameter (Whatif, Confirm) zur Risikoverringerung. Die Tabelle zeigt die Commonparameter mit ihren Entsprechungen der PreferenceVariables. Nicht jeder CommonParameter hat eine korrespondierende PreferenceVariable.

Kapitel

CommonParameter

PreferenceVariable

2.2.1

Verbose

$VerbosePreference

2.2.2

Debug

$DebugPreference

2.2.3

ErrorAction

$ErrorActionPreference

2.2.4

ErrorVariable

 

2.2.5

WarningAction

$WarningActionPreference

2.2.6

WarningVariable

 

2.2.7

OutVariable

 

2.2.8

OutBuffer

 

2.2.9

WhatIf

$WhatIfPreference

2.2.10

Confirm

$ComfirmPreference

Die Liste der Commonparameters stammt aus "about_commonparameters" im Block "Long Description".

2.2.1 Verbose (PreferenceVariable: $VerbosePreference)

Den Commonparameter -Verbose können Skriptprogrammierer einsetzen, um dem Anwender besonders detaillierte Informationen zum Skript zu geben, die nicht für den Normalanwender. sondern nur für PowerUser interessant sind. Der PowerUser gibt dazu beim Skriptaufruf den Übergabeparameter "Verbose_Mode=1" ein. Das Vorhandensein dieses Parameters kann im Skript in einer If-Abfrage geprüft werden, in der die Verbose-Ausgaben definiert sind.

Das cmdlet write-verbose sendet Ausgaben an den Verbose-Stream. Dessen Output ist farblich und durch das Wort VERBOSE: hervorgehoben.
Wenn es aber nur um eine farbliche Hervorhebung einer Ausgabe geht, kann man diese auch sehr einfach mit "write-host" erreichen.

write-host "diese Ausgabe erscheint in Magenta" -foregroundcolor "Magenta"


Beispiel 1: Ausgabe von Verbosemeldungen
für das folgende Beispiel vergewissert Euch bitte, dass die Preference Variable $VerbosePreference den Defaultwert "silentlycontinue" besitzt. Sonst startet bittr die Powershell neu oder weist "SilentlyContinue" der Variablen $Verbosepreference zu

$VerbosePreference

#Ausgabe
SilentlyContinue


gültige Werte für $VerbosePreference (Quelle: about_preference_variables)

Stop

Displays the verbose message and an error message and then stops executing

Inquire

Displays the verbose message and then displays a prompt that asks you whether you want to continue

Continue

Displays the verbose message and then continues with execution.

SilentlyContinue

Does not display the verbose message. Continues executing (Default)


Beispiel 2: Einsatz von Write-Verbose mit dem Commonparameter "Verbose"

function demo_Verbose{
    param($verbose_mode=0)
    
    write-output "dies ist eine normale Ausgabe `n"  
    write-verbose "generell wichtige Info: `n" -verbose
    write-verbose "noch eine wichtige Info, die aber nur angeziegt wird, `
                   wenn `$VerbosePreference = `"continue`"ist: `n"
    
    if($verbose_mode -eq 1) {
        write-verbose "Info wird nur angezeigt, wenn `$verbose_mode = 1 ist" -verbose
    }
}

demo_Verbose 1 # Aufruf der Funktion. $verbose_mode wird auf 1 gesetzt

 

Setzt man die PreferenceVariable vor der Ausführung des Scripts auf "continue", so werden auch Ausgaben von write-verbose angezeigt, die keinen commonparameter haben

$VerbosePreference="continue"

#Ausgabe:

dies ist eine normale Ausgabe

VERBOSE: generell wichtige Info:

VERBOSE: noch eine wichtige Info, die aber nur angeziegt wird,
                   wenn $VerbosePreference = "continue"ist:

VERBOSE: Info wird nur angezeigt, wenn $verbose_mode = 1 ist

 

2.2.2 Debug (PreferenceVariable: $DebugPreference)

Die Debugvariable soll dem Anwender/ Entwickler durch spezielle Informationen helfen,  Fehler zu finden. Die Anwendung dieses Parameters ist synonym zu Verbose aus 2.1.
Anstelle von Write-Verbose ist Write-Debug zu benutzen und die Preferencevariable lautet $DebugPreference

 

2.2.3 Erroraction (PreferenceVariable: $ErrorActionPreference)

Treten in einem Skript Fehler auf, die nicht unbedingt zu einem Abbruch dieses Skriptes führen müssen, wie beispielsweise der Versuch eine nicht vorhandenen Datei zu öffnen, so spricht man von “non-terminating Errors”. Der Programmierer kann bei diesen Fehlern mittels dem Commonparameter -Erroraction entscheiden, wie mit solchen Fehlern verfahren will.

Der Commonparameter –Erroraction überschreibt die PreferenceVariable $ErrorActionPreference für genau einen Befehl. Folgende Verhalten sind mit dem Commonparameter  –Erroraction bei einem “non-terminating Error” wählbar

Value

Kurzform

Verhalten

-ErrorAction SilentlyContinue

-EA 0

Die Fehlermeldungen wird unterdrückt und das Skript weiterausgeführt

-ErrorAction Stop

-EA 1

Die Fehlermeldung wird ausgegeben und das Skript wird gestoppt

-ErrorAction Continue

-EA 2

Die Fehlermeldung wird ausgegeben und das Skript weiterausgeführt

-ErrorAction Inquire

-EA 3

Die erste Fehlermeldung wird ausgegeben und eine Abfrage an den User gestellt wird, ob das Skript weiter ausgeführt werden soll


Im Gegensatz dazu stehen die sogenannten “terminating Errors” wie fehlende Berechtigung oder Syntaxfehler, die von dem Commonparameter -Erroraction  nicht beeinflusst werden können.       

Die Erroraction kann entweder hinter einem Befehl angegeben und gilt dann auch nur für diesen (Beispiel 1a), oder in einer eigenen Zeile mit der Variablen $ErrorActionPreference für alle folgenden Zeilen gesetzt werden (Beispiel 1b).

Beispiel 1a: Unterdrücken von Errormeldungen ohne Abbruch des Skripts für einen Befehl (- Erroraction SilentlyContinue oder -EA 0).

$processes="system","notepad","Dr.No","powershell"  #der Prozess "Dr.No" exisitiert nicht
foreach ($process in $processes) {
get-process $process -ErrorAction SilentlyContinue  #gilt nur für diesen Befehl
}

#Ausgabe

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
   1509       0        0        236     2    12,05      4 System
     40       3     1256       3772    32     0,70   5460 notepad
    466       8    44392      15372   160     1,64   3292 powershell

 

Beispiel 1b: Unterdrücken von Errormeldungen ohne Abbruch des Skripts skriptweit (- Erroraction SilentlyContinue)

$processes="system","notepad","Dr.No","powershell"  #der Prozess "Dr.No" exisitiert nicht
$ErrorActionPreference = "silentlycontinue" #Gilt ab jetzt für alle folgenden Befehle
foreach ($process in $processes) {
get-process $process
}
$ErrorActionPreference = "stop" #setzt die Fehlerbehandlung auf den DefaultStandard zurück

 

Beispiel 2: Ausgabe der ersten Errormeldung mit Abbruch des Skripts (-ErrorAction Stop oder –EA 1)

$processes="system","Dr.No","powershell"
foreach ($process in $processes) {       
get-process $process -ErrorAction Stop
}

#Ausgabe
# Der system-Prozess existiert natürlich und wird ausgegben.
# Beim "Dr.No"-Prozess tritt ein Fehler auf, der das Skript unterbricht
 
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
   1511       0        0        236     2    12,42      4 System
Get-Process : Command execution stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: Cannot find a process with the name 'notepad'. Verify the process name and call the cmdlet again.

At line:2 char:12
+ get-process <<<<  $process -ErrorAction Stop
    + CategoryInfo          : OperationStopped: (:) [Get-Process], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ActionPreferenceStop,Microsoft.PowerShell.Commands.GetProcessCommand

 

Beispiel 3: Ausgabe der Errormeldungen ohne Abbruch des Skripts (-ErrorAction Continue oder –EA 2)

$processes="system","notepad","Dr.No","powershell"
foreach ($process in $processes) {
get-process $process –EA 2
}

#Ausgabe
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
   1509       0        0        236     2    12,78      4 System

Get-Process : Cannot find a process with the name 'Dr.No'. Verify the process name and call the cmdlet again.
At line:2 char:12
    + get-process <<<<  $process -EA 2}
    + CategoryInfo          : ObjectNotFound: (Dr.No:String) [Get-Process], ProcessCommandException
    + FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessCommand

    436       8    44684      18604   160     1,98   3292 powershell

 

Beispiel 4: Unterbrechung des Skripts mit Rückfrage beim User  (-ErrorAction Inquire oder –EA 3)

$processes="system","notepad","Dr.No","powershell"
foreach ($process in $processes) {
get-process $process -EA 3}

#Ausgabe
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
   1509       0        0        236     2    13,08      4 System
 
Confirm
Cannot find a process with the name 'notepad'. Verify the process name and call the cmdlet again.
[Y] Yes  [A] Yes to All  [H] Halt Command  [S] Suspend  [?] Help (default is "Y"): y


Anmerkungen:
Beim Ausführen des Skripts in der Powershell_ISE.exe erfolgt die Abfrage über ein eigenes Fenster

Wie bei Debug "write-debug" und bei Verbose "write-verbose" gibt es für ErrorAction das cmdlet "write-error", mit dem gezielt Errormeldungen im Skript ausgegeben werden können.

write-error "Errormeldung" -Erroraction continue
write "Fehler, aber ich mache weiter"

#Ausgabe

 : Errormeldung
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
 
Fehler, aber ich mache weiter

 

2.2.4 Errorvariable

Eine Errorvariable bietet die Möglichkeit Errormessages in einer Variablen abzuspeichern oder Errormessages an bereits bestehende Messages anzuhängen. Damit lassen sich auch bei der Verwendung von SilentlyContinue Fehlermeldungen analysieren.


Beispiel 1: Errormessages in einer Errorvariablen speichern

$processes="system","notepad","Dr.No","powershell","Dr. Yes"
foreach ($process in $processes) {
get-process $process -ErrorAction SilentlyContinue -ErrorVariable +a
} #das + von +a bewirkt ein Anhängen der neuen Fehlermeldung

"`nAusgabe aller bisherigen Fehler:`n$a"

#Ausgabe

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
   1118       0        0        228     2   125,78      4 System
    419       9    49156      13404   168     5,53   2668 powershell
    306       8    25104        284   140     2,38   2720 powershell

Ausgabe aller bisherigen Fehler:

Cannot find a process with the name 'notepad'. Verify the process namewith the name 'Dr.No'. Verify the process name and call the cmdlet again.

 

2.2.5 WarningAction (PreferenceVariable: $WarningPreference)

Der CommonParameter "WarningAction" arbeitet genauso wie der "ErrorAction" Parameter. WarningAction kann dieselben Werte silentlycontinue, continue, stop und inquire annehmen, wie ErrorAction. Default ist continue.


Beispiel 1: Warnungen und ihre Folgen

write-warning "erstes mal: Letzte Warnung"
write-warning "zum zweiten Mal: Letzte Warnung" -warningAction continue
write-warning "zum dritten Mal: Letzte Warnung" -warningAction silentlycontinue #hört aber keiner
write-warning "zum vierten Mal: Letzte Warnung" -warningAction inquire
write-warning "zum fünften und letzen Mal: Letzte Warnung" -warningAction stop 

#Aufruf des Skripts in der Console

.\demo-WarningAction.ps1

WARNING: erstes mal: Letzte Warnung
WARNING: zum zweiten Mal: Letzte Warnung
WARNING: zum vierten Mal: Letzte Warnung

Confirm
Continue with this operation?
[Y] Yes  [A] Yes to All  [H] Halt Command  [S] Suspend  [?] Help (default is "Y"): y
WARNING: zum fünften und letzen Mal: Letzte Warnung
Write-Warning : Command execution stopped because the preference variable "WarningPreference" or common parameter is se
t to Stop.
At C:\Powershell\website\skripte\commonparameters\demo-WarningAction.ps1:5 char:14
+ write-warning <<<<  "zum fünften und letzen Mal: Letzte Warnung" -warningAction stop
    + CategoryInfo          : OperationStopped: (:) [Write-Warning], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : ActionPreferenceStop,Microsoft.PowerShell.Commands.WriteWarningCommand

 

2.2.6 WarningVariable

Der CommonParameter " WarningVariable" arbeitet genauso wie der "ErrorVariable" Parameter. Wenn man mit cmdlets arbeitet, die Warnings ausgeben können, dann ist dies der geeignete CommonParameter.

2.2.7 Outvariable

Die Ausgabe eines Befehls lässt sich einfach in eine Variable schreiben.

$a=get-process powershell

# Eine Ausgabe von "get-process powershell" in der Console erfolgt nicht

 

Mit dem Einsatz des Commonparameters Outvariable wird dagegen die Ausgabe des Befehls in eine Variable geschrieben und gleichzeitig auch am Bildschirm ausgegeben


Beispiel 1: Ausgabe auf den Bildschirm und gleichzeitig in eine Variable

get-process powershell -outvariable a
# man beachte, dass Variablen ohne $-Zeichen benannt sind. Nur die Ausgabe # von Variablen erfordert ein $-Zeichen

#Ausgabe
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    344       8    44072      28720   160     1,56   2584 powershell
    360       9    27972      39088   139     1,03   3436 powershell

#$a enthält die Ausgabe ebenfalls
$a

#Ausgabe
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    344       8    44072      28720   160     1,58   2584 powershell
    360       9    27972      39088   139     1,03   3436 powershell

 

 Mit einem + Zeichen werden Ausgaben an bestehende Meldungen angehängt

get-process powershell -outvariable a

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    420       8    44072      28852   160     1,58   2584 powershell   

get-process notepad -outvariable +a   #<---Hier steht das + Zeichen
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- ----------
     60       2     1160       4140    30     0,05   1816 notepad

$a
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    420       8    44072      28852   160     1,59   2584 powershell
     60       2     1160       4140    30     0,05   1816 notepad

 

2.2.8 OutBuffer

Der OutBuffer ist ein Parameter, um das Verhalten der Pipeline zu beeinflussen. Da mir nicht viel zu diesem Parameter einfällt und keine weiteren Hinweise gefunden habe, zitiere ich nur die Powershellhilfe

get-help about_commonparameter

#Ausgabe gekürzt

-OutBuffer <Int32>

        Determines the number of objects to accumulate in a buffer before
        any objects are sent through the pipeline. If you omit this parameter,
        objects are sent as they are generated.
       
        This resource management parameter is designed for advanced users.
        When you use this parameter, Windows PowerShell does not call the
        next cmdlet in the pipeline until the number of objects generated
        equals OutBuffer + 1. Thereafter, it sends all objects as they are
        generated.

 

3 automatic Variables

Technet:  about_Automatic_Variables

Über viele Variablen - manchmal sind etwas merkwürdig benamste darunter - im täglichen Powershellleben macht man sich kaum Gedanken, sondern verwendet oder übernimmt diese einfach aus irgendeinem Beispielcode. Gute Beispiele dafür sind die Variablen "$_", $false, $true oder $pwd.

Wie schon anfangs in der Einleitung erwähnt, bringt Powershell etwa 50 derartiger Variablen mit, die unter dem Topic "automatische Variablen" zusammenbefasst sind.
Teilweise enthalten die automatischen Variablen bestimmte Pfade, wie unter Filesystem - automatic Variables beschrieben, teilweise erleichtern sie den Zugriff auf bestimmte Informationen im Skript, wie die Variable $error auf Fehlermeldungen.

Jede einzelne automatic-Variable zu erklären, ist hier meines Erachtens wenig sinnvoll, da erstens im oben genannten Technet-Link die Variablen sehr gut erklärt sind und zweitens die Variablen im praktischen Zusammenhang bei anderen Themen erklärt werden müssen, wie etwa $Error beim Thema "Fehlerbehandlung" oder $_ beim Thema Pipelining.