Behandelte Themen

  1. Bestimmung der .Net-Klasse hinter einem cmdelt
        Beispiel 1: Untersuchen des cmdlets get-date
        Beispiel 2: Anwenden der Klasse System.DateTime
     
  2. der ObjectBrowser
     
  3. TypeAccelerators
     
  4. Assemblies
       Beispiel 1: Auflisten der geladenen Assemblies
       Beispiel 2: Nachladen einer Assembly

 


1 Klassen in .Net

Mit dieser Seite will ich die enge Verknüpfung zwischen Powershell und den .Net-Klassen zeigen. 

 

1.1 Bestimmung der .Net-Klasse hinter einem cmdlet

Beispiel 1: Untersuchen des cmdlets Get-Date

Dieses Beispiel zeigt, wie die dem cmdlet "get-date" zugrunde liegende  .Net-Klasse "System.Datetime" mit dem cmdlet Get-Member bestimmt wird.

Set-StrictMode -Version "2.0"
Clear-Host

 
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

Googelt man nach "System.DateTime MSDN" findet man schnell die zugehörige Klasse in der MSDN, die man sehr oft benötigt, wenn die Informationen in der Powershellhilfe nicht ausreichend sind. (siehe MSDN-Link im nächsten Beispiel)

 

Beispiel 2: Anwenden der Klasse System.DateTime

MSDN: DateTime Structure

[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"
Time is now        = 02/15/2010 09:38:08
Time in UTC now    = 02/15/2010 07:38:08
Time Today is      = 02/15/2010 00:00:00

 

Die hier gezeigten Beispiele verwenden statische Eigenschaften der Klasse DateTime (Now, UTCNow, Today). Erkennbar sind diese statischen Eigenschaften im MSDN-Link: DateTime Properties an dem roten "S"

Nichtstatische Methoden können nur auf Instanzen angewendet werden, die mit dem cmdlet "New-Object" erstellt werden müssen.

Einige weitere Beispiele, wie Objekte der Klasse Datetime erzeugt werden können, findet ihr im Kapitel Das FileSystem -> 2.2.2 Zeiteigenschaften (CreationTime, LastAccessTime, LastWriteTime)  -> Beispiel 3.

 

1.2 .Net Klassen verstehen und verwenden

.Net ist eine riesige Bibliothek an Klassen, die uns Microsoft für die Verwendung in allen modernen MS-Programmiersprachen zur Verfügung stellt. Powershell hat allerdings aus zwei Gründen eine Sonderrolle
  • es fehlen einige Werkzeuge um eigene Klassen zu erstellen
  • mit den cmdlets kann man sehr vieles erreichen, ohne sich dabei mit .Net beschäftigen zu müssen
viele (gute!) Powershellprogrammierer machen daher einen Bogen um .Net, obwohl die Verwendung gar nicht so schwierig ist und .Net oft einen erheblichen Mehrwert hat.

Falls noch nicht geschehen, lasst euch doch mal auf .Net ein.

Die erste Schwierigkeit ist aus den tausenden Klassen die richtige zu finden, wozu es aber ein paar Tricks gibt:
  • Kennt ihr ein cmdlet, dass schonmal in die richtige Richtung geht, so seht euch wie in Kapitel 1.1 beschrieben, die dahinterliegende .Net Klasse an
     
  • Beschränkt euch beim Googlen nicht nur Powershellseiten, sondern seht bewusst in CSharp(C#) und VBSharp(VB#) hinein. Je spezifischer oder ungewöhnlicher eure Aufgaben sind, je eher findet ihr die Ansätze in CSharp-Listings. Um einen User mit Powershell im ActiveDirectory anzulegen, findet ihr 1000nde Beispiel für Powershell, einem User ein bestimmtes Recht zuzuordnen wird schon weniger.
     
  • In der MSDN live oder mit dem Objectbrowser (siehe Kapitel 2) browsen, kann auch interessante Ergebnisse liefern.
Wenn Ihr eine passende Klasse gefunden habt, dann sucht diese Klasse in der MSDN (Google: "<Klassenname>" "MSDN") sollte in den vorderen Treffern den passenden Link liefern

Die zweite Schwierigkeit besteht darin, die MSDN-Seite richtig zu interpretieren. Im Gegensatz zu den cmdlets ist diese Dokumentation sehr knapp und tabellarisch aufgebaut. Eher selten findet sich mal ein Beispielcode. Lasst euch davon aber bitte nicht abschrecken! Mit den nächsten Kapiteln will ich versuchen, die Struktur einer .Net-Klasse und der zugehörigen Dokumentation zu erklären.

Ich werde anhand der beiden Klassen
versuchen zu zeigen, wie man .Net Klassen in der Powershell anwendet und welche Geheimniss man ihnen entlocken kann.

1.2.1 allgemeine Informationen zu einer Klasse

Sehen wir uns mal den ersten Teil der Informationen an, die die MSDN zur Klasse System.IO.FileInfo liefert.
(Wenn es euch möglich ist, solltet ihr die Orginalversion also die englische Sprache verwenden)

  • die Kurzinformation in der grünen Ellipse gibt euch einen kurzen Überblick über den Zweck der Klasse
     
  • der wichtigste Link in diesem Screenshot ist ".NET Framework 4.5 | Andere Versionen". Hier verstecken sich Artikel aus früheren .Net Implementationen dieser Klasse und diese sind keineswegs gleich zur aktuellsten Version. Oft findet man besonders unter .Net 2.0 die meisten und besten Erklärungen einer Klasse und die meisten Beispiele! Unbedingt bei Unklarheiten hier nachschauen!!!

    Vergleicht mal die Informationen zur  Methode "GetCurrentDomain" der Klasse "System.DirectoryServices.ActiveDirectory.Domain"
    MSDN: Domain.GetCurrentDomain Method  - .Net Framework 4.5
    MSDN: Domain.GetCurrentDomain Method  - .Net Framework 2.0

    Im Framework 2.0 Link findet ihr unten ein fertiges Skript -sogar in Powershell geschrieben- , mit dem mit dieser Klasse die FSMO-Role-Holder der Domäne bestimmen werden können. Es ist schade, dass diese erklärende Information so versteckt ist.
     
  • Weiter finden sich noch Namespace und Assembly. Ich benutze in meinen Skripten meist den kompletten Namespace, auch wenn dies oft nicht notwendig ist, also beispielsweise "[System.IO.FileInfo]$File", obwohl "[FileInfo]$File" genauso funktioniert.
     
  • Die Assembly, also die zur Klasse gehörige dll-Datei muss manchmal nachinstalleirt werden (siehe Kapitel 4)
     
  • Auf Constructors, Properties und die weiteren Klassenbestandteile gehe ich gleich näher ein.



Developer Network: System.IO.FileInfo

 

1.2.2 Klassen - Konstruktoren

Der nächste wichtige Punkt auf der Website, den wir gegenfalls aufklappen müssen, sind die Konstruktoren. Mit einem Konstuktor erstellen wir aus einer Klasse eine tatsächliche Instanz, also ein Objekt. Je nach Klasse kann die Objekterstellung ein bischen unterschiedlich geschehen, wie in den drei folgenden Unterkapiteln A,B und C gezeigt.

A) Eine Instanz aus der FileInfo-Klasse erstellen (Konstruktor ohne Überladung)

In diesem Fall haben wir also eine Klasse FileInfo, aber es fehlt ein Objekt (=eine Instanz) auf die wir die Klasse anwenden können. Wir benötigen also ein File, aus dem wir mit dieser Klasse eine Instanz erstellen
(Ich habe hier im WMI-Kapitel versucht, an einem übertragenen Beispiel aus dem täglichen Leben das Verhältnis von Klassen, Objekten, Methoden und Eigenschaften zu beschreiben. Wenn ihr noch Schwierigkeiten mit den eben genannten Begriffen der Objektwelt habt, hilft euch die Beschreibung möglicherweise weiter)

Klappt ihr in der MSDN den "Constructor"-Abschnitt auf, so sieht es dort erfreulich übersichtlich aus


Eine Instanz ist damit schnell erstellt:

$File = "C:\temp\myPicture.jpg"

$FileInfo = New-Object System.IO.FileInfo($File)
#oder etwas kürzer
$FileInfo = [System.IO.FileInfo]$File
#oder etwas kürzer
$FileInfo = [FileInfo]$File

Die Variable $FileInfo stellt nun ein Objekt der Klasse "System.IO.FileInfo" dar, welches meine Datei myPicture.jpg repäsentiert. Mit diesem Objekt kann ich dann die Datei über die Methoden und Eigenschaften der Klasse weiterbearbeiten
 

B) Eine Instanz aus der System.String-Klasse erstellen (Konstruktor ohne Überladung)

Seht ihr euch in der System.String-Klasse den Abschnitt Constructors an, so seht ihr mehr als eine Art von Konstruktoren. Solch eine Konstellation mit mehreren Knstruktoren, die sich durch die Parameterliste unterscheiden, nennt man ÜberladenMSDN: System.String



Je nach Anzahl der im Konstruktor übergebenen Parameter bekommt man also unterschiedliche Ergebnisse

Set-StrictMode -Version "2.0"
Clear-Host

$myArray = @("aa","bb","cc","dd","ee","ff")

$myString0 = [System.String]$myArray
$myString1 = New-Object System.String("Karl_Napf",5,4)
$myString2 = New-Object System.String("K",5)

$myString0
$myString1
$myString2
#Ausgabe

aa bb cc dd ee ff
Napf
KKKKK

Nicht für jeden Konstruktor erschließt sich einem der Sinn. Insbesondere die für die Stringklasse bieten sich natürlich einfachere Mechanismen an. Wichtig ist den Unterschied zwischen überladenen und nicht überladenen Konstruktoren zu kennen.

Die Klasse System.String eignet sich recht gut, um exemplarisch in die .Net Welt einzusteigen. Im Kapitel Variablen 1.2.1 Strings findet ihr zu dieser Klasse viele Beispiele, die zumindest teilweise auch praktischen Wert haben.

C) Eine Instanz aus der System.Net.NetworkInformation.IPGlobalProperties erstellen

Um ein Objekt für die Klasse IPGlobalProperties zu erstellen, benötigen wir zusätzlich eine statische Methode aus der Klasse. Auf "statische Methode" gehe ich im nächsten Kapitel noch genauer ein

MSDN: System.Net.NetworkInformation.IpGlobalProperties

$IPProperties =  [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()

Ein ausgearbeites Beispiel findet ihr unter: Netwerk -> Connectivity
 

1.2.3 Klassen - Methoden

Wie im letzten Kapitel schon angedeutet, muss man bei Methoden zwischen statischen und nicht statischen (=instanzbasierten) Methoden unterscheiden. Im bereits genannten Kapitel Im Kapitel Variablen 1.2.1 Strings versuche ich den Unterschied anhand der String-Klasse zu erklären.

Anstelle der StringKlasse nehme ich Klassen aus dem Namespace "System.DirectoryServices.ActiveDirectory" als Beispiele. Seht euch auf der MSDN in diesem Namespace ruhig etwas um und sucht nach den Klassen "Forest", "Domain" oder "ActiveDirectorySite" und geht in diesen Klassen auf den Abschnitt "Methods".

Beispiel 1: statische Methoden für den eigenen Context
"eigener Context" bedeutet, dass wir uns um unsere eigene Umgebung, also den Forest oder die Domäne, skripttechnisch kümmern wollen, in den wir gerade (="..Current..")angemeldet sind. 

Set-StrictMode -Version "2.0"
Clear-Host

[System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
[System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
[System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite()
#Ausgabe gekürzt

Forest                  : Dom1.Intern
DomainControllers       : {WIN-VSKGC0FLE6E.Dom1.Intern}
...

Name                  : Dom1.Intern
Sites                 : {Default-First-Site-Name}
Domains               : {Dom1.Intern}
...

Name                           : Default-First-Site-Name
Domains                        : {Dom1.Intern}
Subnets                        : {}
Servers                        : {WIN-VSKGC0FLE6E.Dom1.Intern}
...

Wichtig ist zu wissen, dass die drei Methoden GetCurrentDomain, GetCurrentForest und GetComputerSite statisch sind, also keinen Konstruktor benötigen, auf den sie angewendet werden. Die Syntax statischer Klassen seht ihr in dem Beispiel [<Klasse>]::<statische Methode>]
 
Jetzt bleibt nur noch die spannende Frage, wie man solche statischen Methoden findet und als solche identifiziert. In 99% meiner Fälle benutze ich die MSDN als Datenquelle.


Das Erkennungszeichen einer statischen Klasse ist also das rote "s" in der Spalte vor dem Methodennamen. Findet ihr ein solches "s" ist die Benutzung der Methode meist besonders einfach, da keine Instanz mit einem Konstruktor erstellt werden muss.

1.2.3.1 Die Klasse DirectoryContext

MSDN: DirectoryContext Class

Wenn ihr etwas im ActiveDirectory-Namespace forscht, wird euch wahrscheinlich recht oft auch bei den statischen Methoden in irgendeiner Form der Parameter "context" auffallen. "In irgendeiner Form" bedeutet leider,  dass die MSDN-Dokumentation hier nicht ganz konsistent ist. Bei manchen Beschreibungen von Methoden steht context in der Parameterliste, manchmal "domaincontext, forestcontext...", manchmal auch gar nichts. Dann erfährt man erst in der detaillierten Beschreibung, dass der Parameter "context" erforderlich ist.

Über diesen Parameter wird beispielsweise detailliert gesteuert,
  • mit welcher Domäne oder welchem Forest ihr arbeiten wollt
  • welchen Domaincontroller ihr benutzen wollt
  • welche Credentials ihr verwenden wollt
Manchmal wird der Context nicht verwendet, manchmal ist er optional und natürlich gibt es Methoden, bei denen er zwingend gesetzt werden muss

Beispiel 1: Alle GlobalCatalog-Server in einem Forest finden (FindAll-Methode der GlobalCatalalog-Klasse)
Set-StrictMode -Version "2.0"
Clear-Host

$Context = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("Forest","Dom1.Intern")
[System.DirectoryServices.ActiveDirectory.GlobalCatalog]::Findall($context)

1.2.3.2 Überladene Methoden

Wei bei den Konstruktoren gibt es auch bei den Methoden die sogenannte Überladung. Dies bedeutet wieder nichts anderes, als das die Anzahl der übergebenen Parameter variieren kann. Als Beispiel dient hier die hide FindAll-Methode der Klasse DomainController.

MSDN: DomainController-Klasse



Beispiel 1: Alle DomainController finden (FindAll-Methode der DomainController-Klasse)

MSDN: DomainController.FindAll Method (DirectoryContext)

Set-StrictMode -Version "2.0"
Clear-Host

$DirectoryContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("Domain","Dom1.Intern")
[System.DirectoryServices.ActiveDirectory.DomainController]::FindAll($DirectoryContext)


$Context = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("Forest","Dom1.Intern")
[System.DirectoryServices.ActiveDirectory.GlobalCatalog]::Findall($context)

$Context = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("Domain","Dom1.Intern")
[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($Context)

$User = "Administrator"
$Password = "myPassword"
$DirectoryServer = "WIN-VSKGC0FLE6E.Dom1.Intern:389"
$Context = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("DirectoryServer",$DirectoryServer,$User,$Password)
[System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($Context)

1.2.4 Klassen - Eigenschaften

1.2.5 Klassen - Enumerationen

Enumerationen enthalten die Namen einer Eigenschaft.

 

Beispiel 1: Darstellen aller Farben der Console
MSDN: ConsoleColor Enumeration

Set-StrictMode -Version "2.0"
Clear-Host

 
$Colors = [Enum]::GetNames([System.ConsoleColor])

Foreach($Color in $Colors){
   $BackgroundColor = $Color
   $Space = " "*25
   Write-Host  "$Space`n" -BackgroundColor $BackgroundColor -NoNewline
   Write-Host  "$Space$color`n" -BackgroundColor $BackgroundColor -NoNewline
   Write-Host  "$Space`n" -BackgroundColor $BackgroundColor
}

das Egebnis sollte dann in Eurer Console etwa so aussehen:



Beispiel 2: Aufzählen der Hives einer WindowsRegistry
MSDN: RegistryHive Enumeration

Set-StrictMode -Version "2.0"
Clear-Host


$RootHives = [System.Enum]::GetNames([Microsoft.Win32.RegistryHive])
$RootHives
#Ausgabe

ClassesRoot
CurrentUser
LocalMachine
Users
PerformanceData
CurrentConfig
DynData

Mehr Informationen und Beispiele zur Registry findet ihr im Kapitel die Registry und .Net

1.2.6 Klassen - Namespace

 

2 Der Objectbrowser

Den Objectbrowser ist ein 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 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 außerdem 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 außerdem 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 .Net-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

 

Tipp:

Um sich bei häufig benutzten Klassen Tipparbeit zu sparen, kann man die Klasse am Anfang des Skriptes in eine Variable speichern

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

Die Powershell-Syntax ist oft kürzer und wird in den meisten Beispielskripten verwendet, natürlich auch in den Beispielen 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 umgekehrt, was insbesondere bei Websuchen nach Beispielskripten 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. http://blogs.msdn.com/powershell/archive/2006/07/12/type-shortcuts.aspx

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 

$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]
$Drive = [wmi] "Win32_LogicalDisk.DeviceID='L:'"
$Drive.Volumename = "TRAVELDRIVE"
[void]$Drive.Put()

#mit vollständingem Klassennamen
$Drive = [System.Management.ManagementObject]'Win32_LogicalDisk.DeviceID="L:"'
$Drive.Volumename = "TRAVELDRIVE"
[void]$Drive.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

Windows PowerShell Blog > .NET types

Beispiel 2: Nachladen der Assembly

Using .NET Framework Assemblies in Windows PowerShell

[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
 

Beispiel 3a: Bildschirmauflösung bestimmen

$Null = [reflection.assembly]::loadwithpartialname("System.Windows.Forms") 
[System.Windows.Forms.Screen]::AllScreens 

#mögliche Ausgabe bei zwei Bildschirmen

 

BitsPerPixel : 32
Bounds       : {X=-1600,Y=0,Width=1600,Height=900}
DeviceName   : \\.\DISPLAY1
Primary      : False
WorkingArea  : {X=-1600,Y=0,Width=1600,Height=860}
 
BitsPerPixel : 32
Bounds       : {X=0,Y=0,Width=1920,Height=1080}
DeviceName   : \\.\DISPLAY2
Primary      : True
WorkingArea  : {X=0,Y=0,Width=1920,Height=1040}

MSDN: Screen Class

 

Beispiel 3b: Bildschirmauflösung bestimmen

$Null = [reflection.assembly]::loadwithpartialname("System.Windows.Forms")
 
[System.Windows.Forms.Screen]::AllScreens | Foreach{
 $_.DeviceName
 "Resolution: $($_.Bounds.Width) * $($_.Bounds.Height)"
 ""
 }

#mögliche Ausgabe

 

\\.\DISPLAY1
Resolution: 1600 * 900
 
\\.\DISPLAY2
Resolution: 1920 * 1080