Behandelte Themen
Bestimmung der .Net-Klasse hinter einem cmdelt
Beispiel 1: Untersuchen des cmdlets get-date
Beispiel 2: Anwenden der Klasse System.DateTimeder ObjectBrowser TypeAccelerators Assemblies
Beispiel 1: Auflisten der geladenen Assemblies
Beispiel 2: Nachladen einer Assembly
*********************************************************************************************************************
1 Bestimmung der .Net-Klasse hinter einem cmdelt
Beispiel 1: Untersuchen des cmdlets get-date
Dieses Beispiel zeigt, wie die dem Powershell-cmdlet "get-date" zugrunde liegende .Net-Klasse "system.datetime" mit get-member bestimmt wird.
get-date | get-member
#verkürzte Ausgabe
TypeName: System.DateTime
Name MemberType Definition
---- ---------- ----------
Add Method System.DateTime Add(System.TimeSpan value)
AddDays Method System.DateTime AddDays(double value)
AddHours Method System.DateTime AddHours(double value)
die .Net-Klasse findet sich in der Zeile" TypeName: System.DateTime"
#Alternativ mit gettype()
(get-date).gettype().fullname
#Ausgabe
System.DateTime
Beispiel 2: Anwenden der Klasse System.DateTime
MSDN:
#Skript
[System.DateTime] $date1 = [System.DateTime]::Now
[System.DateTime] $date2 = [System.DateTime]::UtcNow
[system.datetime] $date3 = [system.DateTime]::Today
"Time is now = $date1"
"Time in UTC now = $date2"
"Time Today is = $date3"
#Ausgabe
Time is now = 02/15/2010 21:37:32
Time in UTC now = 02/15/2010 20:37:32
Einige weitere Beispiele, wie Objekte der Klasse Datetime erzeugt werden können, findet ihr im Kapitel
2 Der Objectbrowser
Den Objectbrowser ist ein sehr nützliches, grafisches Tool zur Erforschung der .Net-Welt. Man kann damit .Net Klassen finden und deren Methoden und Eigenschaften herauslesen.
Mit VisualStudio2005 lässt sich nur .Net2.0 durchsuchen, ab VisualStudio2008 lässt sich auswählen, welches .Net-Paket durchsucht werden soll.
Der Objektbrowser ist in den völlig freien Express-Versionen von VisualStudio ebenfalls uneingeschränkt verfügbar
Über den Objektbrowser kann man zu jeder Methode/ Eigenschaft eine kurze Erklärung lesen. s.u. Im Objektbrowser können ausserdem Eigenschaften/ Methoden aufgeführt werden, die in der Powershell nicht direkt aufrufbar sind z.B. die static-Eigenschaft “maxvalue” der Klasse [system.datetime] (s. Beispiel unten)
Über den Objektbrowser kann man zu jeder Methode/ Eigenschaft eine kurze Erklärung lesen. s.u. Im Objektbrowser können ausserdem Eigenschaften/ Methoden aufgeführt werden, die in der Powershell nicht direkt implementiert sind z.B. die Eigenschaft “maxvalue”

Die Programmierung mittels Powershell-cmdlets und dem direkten Zugriff auf .Net-Klassen ist meist äquivalent. Nicht immer können alle Möglichkeiten der direkten DotNet-Programmierung auch über cmdelts erreicht werden können (z.B. [system.datetime]::maxvalue).
Folgende Beispiele zeigen Entsprechungen zwischen der DotNet und der PowershellSyntax
Dotnet-Syntax | Powershell-Syntax |
[system.datetime]::now | get-date oder (get-date).datetime |
[system.datetime]::now.addDays(3) | (Get-date).addDays(3) |
[system.datetime]::maxvalue | Keine direkte Entsprechung, da Static |
Tipp:
Um sich bei häufig benutzten Klassen Tipparbeit zu sparen, kann man die Klasse am Anfang des Skriptes in eine Variable speichern
#Skript
$datetime=[system.datetime]
$datetime::now
#ist identisch zu
[system.datetime]::now
Wann sollte man welche Syntax benutzen?
Wie man oben erkennen kann, kann man mit beiden Schreibweisen die identischen Befehle absetzen, zumindest meistens.
Ausnahmen sind, zumindest habe ich bis jetzt noch kein Beispielskript gefunden, statische Methoden und Eigenschaften. Dies gelingt nur über die .NET Syntax
Die Powershell-Syntax ist oft kürzer und wird in den meisten Beispielskripten verwendet, natürlich auch die Beispiele in der Powershellhilfe. Mit der DotNet-Schreibweise kann man einheitlich auf die gesamte DotNet Welt zugreifen. Bei weitem nicht für alle Klassen gibt es Powershell-Entsprechungen. Der Objektkatalog erleichtert die Suche nach der richtigen Klasse sehr.
Ein weiterer Vorteil ist die relativ leichte Portierbarkeit eines Powershellscripts in eine Sprache unter VisualStudio wie z.B. VisualBasic und umgekehr, was insbesondere bei Websuchen nach Beispielscripten sehr hilft.
Im Normalfall nutze ich die Powershell cmdlets. Trotzdem halte ich das Verständnis der dotnet-Syntax für sehr hilfreich, Powershellskripte zu verstehen. Gelegentlich z.B. im Bereich ActiveDirectory bringt der direkte DotNet-Zugriff Ergebnisse, die mit Powershell cmdlets schwieriger zu erreichen gewesen wären.
3 TypeAccelearators/ TypeShortcuts
TypeAccelearators bzw. TypeShortcuts sind Abkürzungen von Klassennamen.
TypeShortcut | Full Classname |
[Adsi] | [System.DirectoryServices.Directoryentry] |
[array] | [System.Array] |
[hashtable] | [System.Collections.Hashtable] |
[psobject] | [System.Management.Automation.PSObject] |
[ref] | [System.Management.Automation.PSReference] |
[regex] | [System.Text.RegularExpressions.Regex] |
[scriptblock] | [System.Management.Automation.ScriptBlock] |
[switch] | [System.Management.Automation.SwitchParameter] |
[type] | [System.Type] |
[wmi] | [System.Management.ManagementObject] |
[wmiclass] | [System.Management.ManagementClass] |
[wmisearcher] | [System.Management.ManagementObjectSearcher] |
[xml] | [System.Xml.XmlDocument] |
Mit diesen Shortcuts kann man sich Tippaufwand sparen und die Syntax ist einprägsamer, als ausgeschriebene Klassennamen. Trotzdem ist wichtig auch die Klassennamen hinter einenTypeAccelerator zu kennen, um z.B. im Objectkatalog eine Klasse zu untersuchen.
Referenzen:
Vgl.
Vgl. Windows-Powershell "kurz-gut" "Lee Holmes" 1. Auflage , S54
Die drei folgenden Beispiele zeigen den Einsatz von Typeshortcuts im Vergleich zur ausgeschriebenen Klassen
Beispiel 1 [ADSI]: Verbinden auf ein AD-Objekt
#Skript
#Variablendefintion
$userDN="CN=Administrator,CN=Users,DC=dom1,DC=de"
# .Net Schreibweise"
$User = [System.DirectoryServices.DirectoryEntry]"LDAP://$userDN"
# Type-Accelerator ADSI
$user=[ADSI]"LDAP://$userDN"
Beispiel 2 [WMI]: Umbenennen eines logischen Laufwerks (USB-Stick)
#mit powershell-cmdlet: get-wmiobject
$drive=get-wmiobject "win32_logicaldisk where name='L:'"
$drive.volumename="TRAVELDRIVE"
$[void]$drive.put()
#mit Typeaccelerator [wmi]
$drv=[wmi] "Win32_LogicalDisk.DeviceID='L:'"
$drv.volumename="TRAVELDRIVE"
$[void]$drv.put()
#mit vollständingem Klassennamen
$drv=[System.Management.ManagementObject]'Win32_LogicalDisk.DeviceID="L:"'
$drv.volumename="TRAVELDRIVE"
$[void]$drv.put()
Beispiel 3 [Array]: Umwandlung (Casten) von skalaren Objekten in ein Feld
#mit dem Typeaccelerator
$a = [array] 6,9
$a[1]
#Ausgabe
9
#über die system-Klasse
$a = [system.array] 16,19
$a[1]
#Ausgabe
19
#Kurzform
$a = 26,29
$a[1]
#Ausgabe
29
4 Assemblies
Ein Assembly ist unter .Net eine Einheit von ausführbarem Code, der als Bibliothek (*.dll) oder als Programm (*.exe) vorliegt. Eine Assembly kann aus mehreren Dateien bestehen, die aber nur gemeinsam weitergegeben werden können. Auf einem Rechner können mehrere Versionen von Assemblies nebeneinander existieren.
Assemblies können entweder im sogenannten Global Assembly Cache (GAC) zentral gepeichert sein unter c:\windows\assembly oder im Programmverzeichnis des auszuführenden Programms. Die Struktur von c:\windows\assembly wird übrigens vom Windowsexplorer nicht korrekt angezeigt. Die korrekte Struktur erkennt man z.B. über die Commandline.
Für die Programmierung unter Powershell ist wichtig, dass die Assemblies die Klassen enthalten. Um die Klassen einer Assembly nutzen zu können, muss die Assembly von Powershell geladen werden. Default lädt Powershell bereits die wichtigsten Assemblies, werden zusätzliche Assemblies benötigt, müssen diese im Code geladen werden.
Beispiel 1: Auflisten der geladenen Assemblies
[appdomain]::currentdomain.getassemblies() |sort -property fullname | format-table fullname
#Ausgabe
FullName
--------
Microsoft.PowerShell.Commands.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
Microsoft.PowerShell.Commands.Management, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
Microsoft.PowerShell.Commands.Utility, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
Microsoft.PowerShell.ConsoleHost, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
Microsoft.PowerShell.Security, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
Microsoft.WSMan.Management, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Configuration.Install, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Management, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Management.Automation, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Beispiel 2: Nachladen der Assembly
[void][reflection.assembly]::LoadWithPartialName("System.DirectoryServices.Protocols")
[appdomain]::currentdomain.getassemblies() |sort -property fullname | format-table fullname
#Ausgabe gekürzt
FullName
--------
...
System.DirectoryServices, Version=2.0.0.0, Culture=neutral,
System.DirectoryServices.Protocols, Version=2.0.0.0, Culture=neutral, #<---- wurde nachgeladen
System.Drawing, Version=2.0.0.0, Culture=neutral,
.....
Im VisualStudio entspricht dies dem Hinzufügen eines Verweises