0.  Einleitung
Ganz allgemein gesprochen sind Variablen Speicherstellen im Hauptspeicher eures Rechners, an und von denen Werte geschrieben  und ausgelesen werden können. Der Zugriff erfolgt über einen Bezeichner wie etwa "$a" oder "MyVariable".

0.1 verschiedene Arten von Variablen
                       
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
          Beispiel 4: Ausführbare Datei, um Zufallsstrings und Dateien zu 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

0.1 verschiedene Arten von Variablen

Powershell unterscheidet drei verschiedene Variablentypen.

MSDN: about_Variables

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

$Zahl = 5
$Text = "Powershell"


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

Technet: about_preference_variables

Technet: about_commonparameters


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 "$_". Ab der Powershell V3.0 bekommt die Variable $_ mit $PsItem ein leichter lesbares Synonym an die Seite gestellt.
 "$_" ist die Grundlage für das Pipelining der Powershell, das in fast jedem Powershellskript vorkommt, wobei wiegesagt ab V3.0 $_ häufiger durch leichter lesbare Ausdrücke wie $PsItem ersetzt werden kann.
Auch andere Automatic Variablex 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 -> Pfade -> 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 sein:

  • 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 

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 Zuordnung zur passenden Klasse meist selbst. Sollte sich herausstellen, dass 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, damit keine Informationen verloren gehen. Meist muss sich der Programmierer um nichts kümmern.

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

Powershell bietet natürlich auch die Möglichkeit an, Variable manuell einer Klasse zuzuweisen oder in den 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 eine (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 anschließend den Variablentyp ab. In 99% der Fälle passt der von Powershell ausgewählte Variablentyp

a) WertObjekt der Klasse Int32

$a = 2 #WertObjekt der Klasse Int32
$a.GetType() | Format-Table Name,BaseType -auto

#Ausgabe

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



b) WertObjekt der Klasse Double

$b = 5.5   #Double
$b.GetType() | Format-Table Name,BaseType -auto

#Ausgabe 
 
Name   BaseType        
----   --------        
Double System.ValueType


Objekt der Klasse Boolean

$c = (4 -lt 6)   #Boolean
$c.GetType() | Format-Table Name,BaseType -auto

#Ausgabe

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



Objekt der Klasse String

$d = "hello"  #String
$d.GetType() | Format-Table Name,BaseType -auto

#Ausgabe

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

 

System.Array-Objekt

$e = 1,2,6,9   
$e.GetType() | Format-Table Name,BaseType -auto

#Ausgabe

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

 

Hashtabelle

$f = @{Projektleiter = "Karl Napf";

       TechnischerRedakteur = "Heinz Kunz"

      }  
$f.GetType() | Format-Table Name,BaseType -auto

#Ausgabe

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


Managementobjekt oder WMIObjekt

$g = Get-WmiObject Win32_Bios 
$g.GetType() | Format-Table Name,BaseType -auto

#Ausgabe

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

 

System.IO.FileSystemInfo

$h = ([IO.DirectoryInfo]"C:\")   #.Net-Objekt der Klasse DirectoryInfo
$h.GetType() | Format-Table Name,BaseType -auto

#Ausgabe

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

 

System Array (Enumeration)

$i = [System.Enum]::GetValues([System.Environment+SpecialFolder])
$i.GetType() | Format-Table Name,BaseType -auto

#Ausgabe

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




Beispiel 2a: Implizite Typkonvertierung (Ganzzahl zu Kommazahl)

$MyString = 6 #WertObjekt der Klasse Int32
$MyString.GetType() | Format-Table Name,BaseType -auto

$MyString = $a+0.5
$MyString.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, wie in diesem Beispiel durch "$a=$a+0.5", die Variable einen Nachkommaanteil erhalten , so wandelt Powershell $a automatisch in ein Objekt der Klasse Double um.
 

Beispiel 2b: Implizite Typkonvertierung (Wertebereich überschreiten)

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, wie in diesem Beispiel durch $b=$b+2147483647, die Variable den Wertebereich von [Int32]  übersteigen, so wandelt Powershell $a automatisch in ein Objekt der Klasse Double um.
 

Beispiel 2c: Fehlgeschlagene implizite Typkonvertierung

[Int16]$b = 6 #WertObjekt der Klasse Int16
$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

Dass die implizite Typumwandlung nicht immer funktioniert, zeigt dieses Beispiel einer Variable vom Typ [Int16]. Lässt man deren Wert über den Maximalwert 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 Type

[Int32]$a = 7

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

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

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

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

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
$ofs = " " #Preference Variable

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

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

#Ausgabe

Ausgabe als Array
Karl

Napf

Ausgabe als umgewandelten String
Karl Napf

Amerkungen

  • - Im Gegensatz zu $a=@() definiert [string[]]$a  $a als Array, dessen Elemente nur Strings sein dürfen. siehe Technet: about_Arrays
  • - $ofs (Output Field Separator) ist ein Beispiel für eine Preference Variable. Details dazu findet ihr weiter unten im Kapitel 2.1 Preference Variables
  •  

Beispiel 3: Alphanumerische Zufallswerte erzeugen

Set-StrictMode -Version "2.0"
Clear-Host  

Function Main{
  New-AlphanumericRandom -Digits 500 -NumberOfLines 4 -Flags 11111 -DefinedString "Error:4711"
  #Get-Help New-AlphanumericRandom -Detailed
}
 
Function New-AlphanumericRandom{
  <#
  .Synopsis
  Generiert zufällige alphanumerische Strings

  .PARAMETER Digits
  Länge des zurückgegebenen Strings

  .PARAMETER NumberOfLines
  Anzahl der Zeilenumbrüche = Anzahl Zeilen
 
  .PARAMETER DefinedString
  Dieser String soll im Zufallsstring auftauchen

  .PARAMETER Flags
  Flag 0: 11110 keine Kleinbuchstaben werden im zurückgegebenen String enthalten sein
  Flag 1: 11101 keine Großbuchstaben werden im zurückgegebenen String enthalten sein
  Flag 2: 11011 keine Zahlen werden im zurückgegebenen String enthalten sein
  Flag 3: 10111 keine Leerzeichen werden im zurückgegebenen String enthalten sein
  Flag 4: 01111 kein fester String wird im zurückgegebenen String enthalten sein
  Flag 5: 11111 keine Zeilenumbrüche werden im zurückgegebenen String enthalten sein  

  #>
   Param([int]$Digits=20,[string]$Flags='00111',$NumberOfLines = 2,$DefinedString)
   $RandomPool=$null

   $Flags=[Convert]::ToInt32($Flags, 2) #Konvertierung als Binärwert
   
   $MinLower=[Int][Char]'a' #97
   $MaxLower=[Int][Char]'z' #122

   $MinUpper=[Int][Char]'A'  #65
   $MaxUpper=[Int][Char]'Z'  #90

   $MinNumber=[Int][Char]'0' #48
   $MaxNumber=[Int][Char]'9' #57

   $Space =[Int][Char]' ' #32

   if($Flags -band 1){
     $RandomPool=[Char[]]($MinLower..$MaxLower)
   }
 
   if($Flags -band 2){
     $RandomPool+=[Char[]]($MinUpper..$MaxUpper)
   }
 
   if($Flags -band 4){
     $RandomPool+=[Char[]]($MinNumber..$MaxNumber)
     }

    
   if($Flags -band 8){
     for($i=1;$i -le 3;$i++){
       $RandomPool +=$DefinedString
     }
   }

   if($Flags -band 16){
      for($i=1;$i -lt $NumberOfLines;$i++){
       $RandomPool +=[Environment]::NewLine
       }
    }
   
   #Spacecharacter
   if($Flags -band 8){
     for($i=1;$i -le 10;$i++){
       $RandomPool +=" "
     } #for
   }
   
   #Output Field Separator siehe "Die Variablen" -> "2.1 PreferenceVariables"
   $ofs = ''

  [string](Get-Random -input $RandomPool -count $digits)
}#function Ende

Main
#mögliche Ausgabe

25hKwError:4711Error:4711mT
6HF nWsq B YNjciOzUEkPA 8CZltXISMyD1odG pLVJfb0Qx9ae RError:4711 4
gv
  3ru7

 

Dieses Beispiel ist mir beim Schreiben des Kapitels Texte und Textdateien eingefallen. Dort hatte 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.

Durch die 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.

Um das Erstellen von Zufallsstrings und Textdateien mit zufälligen Inhalt zu vereinfachen, habe ich die Funktion oben kompiliert und eine GUI dazu erstellt:

 

Beispiel 4: Ausführbare Datei, um Zufallsstrings und Dateien zu erzeugen

 CreateRandomString.zip

Damit kann man sich einfach Zufallstrings und Zufallsdateien erzeugen

 

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.
Ich verzichte 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 "String- und Textdateianalyse"

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 " String- und Textdateianalyse" werde ich tiefer auf die "Analyse und Manipulation von Strings" eingehen.

 

1.2.1.1.1 Instanzbasierte Methoden der String-Klasse

 

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

Set-StrictMode -Version "2.0"
Clear-Host  

$MyString = "Napf"
#Gleichbedeutend mit
$MyString = [System.String]"Napf"

$MyString | Get-Member | select -first 3

#Ausgabe

  TypeName: System.String

Name      MemberType Definition                 
----      ---------- ----------        
Clone     Method     System.Object Clone(), System.Object ICloneable.Clone()                                                    
CompareTo Method     int CompareTo(System.Object value), int CompareTo(string strB), ...
Contains  Method     bool Contains(string value)

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 Eigenschaften und Methoden auf Instanzen anwendbar, die kein rotes "S" für "Static" in der linken Spalte stehen haben.

Für die instanzbasierte Methoden (also solche ohne rotes "S") der Stringklasse, die wir uns in Beispiel 1 oder der MSDN angesehen haben, ein paar kleine Beispiele


 

Beispiel 2a: Beginn und Ende eines Strings vergleichen (StartsWith, EndWith)

Set-StrictMode -Version "2.0"
Clear-Host  


[System.String]$a = "KarlNapf"
#die explizite Typeangabe ist natürlich nicht notwendig und hat

  #nur nochmal verdeutlichenden Charakter

$MyString.StartsWith("Karl")
$MyString.EndsWith("Erwin")

#Ausgabe

True
False

 

Beispiel 2b: Umwandlung in Groß- und Kleinbuchstaben (ToUpper, ToLower)

Set-StrictMode -Version "2.0"
Clear-Host 


$MyString = "KarlNapf"
$MyString.ToUpper()
$MyString.ToLower()

#Ausgabe

KARLNAPF
karlnapf

 

Beispiel 2c: Länge eines Strings bestimmen (Length)

Set-StrictMode -Version "2.0"
Clear-Host  


$MyString = "KarlNapf"
$MyString.Length

#Ausgabe

8


1.2.1.1.2 statische 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)

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" in der linken Spalte stehen haben.



Für die statische Methoden (also solche mit einem roten "S") 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

Set-StrictMode -Version "2.0"
Clear-Host  


$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 sowohl Konten erkennen, deren Beschreibngsfeld noch nie (=$Null) belegt war, wie auch Konten deren Beschreibung (=$Empty) gelöscht wurde. 


Beispiel 2b: Vergleich zweier Strings

Set-StrictMode -Version "2.0"
Clear-Host  


$MyString_a = "KarlNapf"
$MyString_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 ebenso 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 tut 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 im voran gegangenen Kapitel gezeigt, schon eine ganze Reihe von Möglichkeiten zurück, was man mit Strings über statische und nichtstatische Methoden sowie mit  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)

$MyString = New-Object System.String("Karl_Napf",5,4)
$MyString
#Ausgabe

Napf
 

MSDN: String-Konstruktor (Char, Int32)
Wiederholung eines Unicode-Zeichens ("K"), so of wie angegeben (5)

$MyString = New-Object System.String("K",5)
$MyString
#Ausgabe

KKKKK

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

$MyString = "KarlNapf"*5
$MyString
#Ausgabe

KarlNapfKarlNapfKarlNapfKarlNapfKarlNapf

5* "KarlNapf" funktioniert übrigens nicht, da Powershell so die automatischen Typumwandlung nicht schafft.
 

MSDN: String-Konstruktor (Char*)

$MyString = New-Object System.String("KarlNapf")
$MyString -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

Set-StrictMode -Version "2.0"
Clear-Host  


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

$MyString
#Ausgabe

User        User01
OS          Windows_NT
Var         KarlNapf
Ausdruck    5

Anmerkung 1 die Sonderzeichen `t und `n stehen für  “horizontal tab” und “new line”.

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

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. Dann benutzt man eher nicht die Escape_Characters

$var = "KarlNapf"

"{0,-15} {1}" -f "User:",$env:username
"{0,-15} {1}" -f "OS:",$env:OS
"{0,-15} {1}" -f "Var:",$var
"{0,-15} {1}" -f "Ausdruck:","$(2+3)"

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

Der Escapecharakter besitzt 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, dass der Befehl in der nächsten Zeile des Codes weitergeschrieben wird. Der Escapecharakter wird außerhalb der Powershell auch häufiger als Backtick bezeichnet

$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.
  • 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.
  • Auf Here-Strings können natürlich alle .Net-Methoden und Eigenschaften der String-Klasse angewendet werden.
  • Here-Strings werden beim Verfassen größerer Texte, z.B. für die OnlineHilfe eines Skriptes, eingesetzt.

Beispiel 1: Definition eines Multilinestrings

Set-StrictMode -Version "2.0"
Clear-Host  


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

$MyString
$MyString.Length
$MyString.gettype() | Format-Table Name,BaseType -Auto
#Ausgabe

Erste Zeile
Zweite Zeile
Dritte Zeile
39

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

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

Set-StrictMode -Version "2.0"
Clear-Host
 

$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] | Get-Member -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 DatenTypen 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] | Get-Member -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 "Scriptblock" und nicht wie bei Funktionen entweder ein Array oder ein ValueType (abhängig von der Return-Anweisung in der Funktion)
Ein Skriptblock ist beispielsweise 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 

Set-StrictMode -Version "2.0"
Clear-Host  


$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

Set-StrictMode -Version "2.0"
Clear-Host  


$ScriptBlock={
 $a=8
 $b=7
 "{0} + {1} = {2}" -f $a,$b,$($a+$b)
}
$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 interessanter, wie die nachfolgenden Beispiele zeigen werden

MSDN: ScriptBlock-Methods


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

Set-StrictMode -Version "2.0"
Clear-Host  


$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

Set-StrictMode -Version "2.0"
Clear-Host  


$ScriptBlock01 = {$i}
For($i=1;$i -le 2; $i+=1){&$ScriptBlock01}

$ScriptBlock02 = {"`nHallo Karl"}
If(2 -gt 1){&$ScriptBlock02}
#Ausgabe
1
2

Hallo Karl

In einem Skriptblock kann auch längerer Code verarbeitet werden.

Beispiel 2: Parameterübergabe in einen Skriptblock

MSDN: ScriptBlock.Invoke-Method
MSDN: ScriptBlock.InvokeReturnAsIs - Method

Laut MSDN ist die Methode InvokeReturnAsIs() effizienter. 

Set-StrictMode -Version "2.0"
Clear-Host  


$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

Set-StrictMode -Version "2.0"
Clear-Host  


$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 wird


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.

Set-StrictMode -Version "2.0"
Clear-Host  


$Array="test1","test2","test3"
[String]$Array
#Ausgabe
test1 test2 test3

$OFS wird im folgenden Beispiel zu "+++"

Set-StrictMode -Version "2.0"
Clear-Host  


$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 es 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 zehn Parameter. Die beiden Parameter "Whatif" und "Confirm" dienen der Risikoabschätzung beim Entwickeln von Skripten. 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"

#Ausgabe

diese Ausgabe erscheint in 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 bitte 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
#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

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

 

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-Ürocess $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 set 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
#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

man beachte, dass Variablen ohne $-Zeichen benannt sind. Nur die Ausgabe von Variablen erfordert ein $-Zeichen

$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,56   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.

 
 
 
 
 
Anhänge:
Diese Datei herunterladen (createRandomString.zip)createRandomString.zip[ ]97 kB
Diese Datei herunterladen (Kap1.1.2_Bsp3.ps1.txt)Kap1.1.2_Bsp3.ps1.txt[ ]2 kB