Hosting der Windows PowerShell in .NET-Anwendungen
Die oftmals sehr prägnanten Commandlets der Windows PowerShell kann man sich auch in .NET-Anwendungen zu nutze machen.
- Dr. Holger Schwichtenberg
Die Windows PowerShell zeichnet sich oft durch prägnante Befehle aus, zum Beispiel
gps | where { $_.ws -gt 1MB } | sort ws -desc | select -first 15
Dieser Befehl bedeutet: Hole die Liste aller Prozesse, filtere diejenigen aus, die mehr als ein MByte Speicher nutzen, sortiere die Liste absteigend nach der Speichernutzung und begrenze die Liste auf die ersten 15.
Auch viele Microsoft-Services und -Server unterstützen Commandlets, ein gutes Beispiel ist das Commandlet New-Mailbox" zum Anlegen von Postfächern für Microsoft Exchange.
Windows PowerShell basiert auf .NET, und daher kann man PowerShell als Skriptumgebung auch innerhalb von .NET-Anwendungen (C#, Visual Basic, C++/CLI, F#, u.v.a.m.) nutzen.
Das Listing zeigt eine Hilfsmethode zum AusfĂĽhren eines PowerShell-Befehls in einer .NET-Anwendung. Voraussetzung ist es, die System.Management.Automation.dll zu referenzieren und ein using System.Management.Automation ist auch hilfreich. Die Methode liefert die Ergebnisobjekte im RĂĽckgabewert und ĂĽber den Out-Parameter-Status aufgetretene Fehler. Zentral ist in der Methode die Instanziierung der Klasse PowerShell mit der statische Methode Create(), die Ăśbergabe der Befehle mit AddScript() und die AusfĂĽhrung mit Invoke().
public Collection<PSObject> Run(string Command, out string Status)
{
string e = "";
PowerShell ps = PowerShell.Create();
// Befehl hinzufĂĽgen
ps.AddScript(Command);
// Befehl ausfĂĽhren
Collection<PSObject> ErgebnisMenge = ps.Invoke();
// Fehler?
if (ps.Streams.Error.Count == 0)
{ // Nein
Status = "OK";
return ErgebnisMenge;
}
else
{ // Es gab einen Fehler
foreach (var dr in ps.Streams.Error)
{
e += dr.Exception.Message;
}
Status = e;
return null;
}
}
Das zweite Listing zeigt den Aufruf der Hilfsmethode an einem Beispiel. Es lassen sich wahlweise Befehlsketten oder ein Pfad zu einer PowerShell-Skriptdatei ĂĽbergeben.
string Status = "";
string Demo = (gps | where { $_.ws -gt 1MB } | sort ws -desc
| select -first 15 ");
var ErgebnisMenge = new WPSHostLib.WPSHost().Run(Demo, out Status);
if (Status != "OK")
{
Console.WriteLine("Fehler: " + Status);
}
else
{
// Ergebnismenge darstellen
foreach (System.Management.Automation.PSObject Ergebnis in ErgebnisMenge)
{
Console.WriteLine(
"{0,-24}{1,-10}{2}",
Ergebnis.Members["ProcessName"].Value,
Ergebnis.Members["Id"].Value,
Ergebnis.Members["WorkingSet64"].Value);
}
}
FĂĽr einen Kunden schreibe ich gerade einen Webservice, der PowerShell-Skripte auf einem Application Server ausfĂĽhrt. Die obige Hilfsroutine ist dabei ein wesentlicher Baustein.