PowerShell Scripte in .NET Anwendungen

Die Windows PowerShell ist eine sehr leistungsfähige Konsole, die mit stark geprägten Befehlen daher kommt. Diese ermöglichen eine ausführliche Aktionsreichweite unter Windows-Systemen. Oft sind sehr ähnliche Anforderungen oder gar die Anforderung diese Scripte ausführen zu können auch an uns Entwickler gestellt. Nun mit der Hilfe vom Microsoft .NET 4.0 und der Assembly „System.Management.Automation.dll“ ist dies auf sehr einfachem Wege möglich (.NET 4.0 ist hier leider die minimal Version, zumindest bei der Installation über NuGET, die mir bis dato als einzige bekannt ist). Um dies nun nutzen zu können, sollten wir also zunächst über die Paket-Konsole von NuGET folgende Aktion ausführen:

Install-Package System.Management.Automation

Hiermit wird die bereits genannte Assembly in unser Projekt installiert. Im Weiteren können wir uns der implementierung widmen. Ich werde dies hier anhand einer Konsolenanwendung vornehmen. Es funktioniert jedoch natürlich auch unter WPF und WinForms sowie ASP. Für das folgende Beispiel werden noch zusätzlich folgende Using-Directives benötigt:

using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Management.Automation;
using System.Text;

Und anschließend (hier aufgrund der Konsolenanwendung statisch) können wir uns der Implementierung widmen.

public static Collection<PSObject> Run(string script)
{
    PowerShell shell = PowerShell.Create();
    shell.AddScript(script);

    Collection<PSObject> result = shell.Invoke();

    if (shell.Streams.Error.Count > 0)
        throw new InvalidPowerShellStateException(shell.Streams.Error.Aggregate(string.Empty, 
                                                    (current, error) => current + error.Exception.Message));

    return result;
}

Wie hier zu sehen ist, ist das Ausführen von Scripts nicht weiter aufwendig. Im „script“ Parameter kann hierbei direkt das Script stehen oder auch ein Pfad zur entsprechenden Scriptdatei. Aber wie ist das Ganze nun zu verwenden? Nun wollen wir uns doch erstmal für dieses Beispiel einen einfachen PowerShell-Befehl nehmen.

$rssUrl = "http://kruse-familie.eu/feed/"
$blog = [xml](New-Object System.Net.WebClient).DownloadString($rssUrl)
$blog.rss.channel.item | select title -First 8

Das hier verwendete PowerShell-Script lädt aus dem RSS-Feed dieses Blogs die letzten acht Einträge und gibt diese wieder. Aber wie können wir nun das Result auswerten? Nichts leichter als das. Hier der Code welcher meine „Main“-Funktion ziert und zusammen mit der obigen „Run“-Methode bereits die volle Konsolenanwendung mit Exceptionhandling zur Verfügung stellt.

static void Main()
{
    try
    {
        StringBuilder script = new StringBuilder();
        script.AppendLine("$rssUrl = \"http://kruse-familie.eu/feed/\"");
        script.AppendLine("$blog = [xml](New-Object System.Net.WebClient).DownloadString($rssUrl)");
        script.AppendLine("$blog.rss.channel.item | select title -First 8");

        Collection<PSObject> result = Run(script.ToString());

        int currentPosition = 1;
        foreach (PSObject powerShellObject in result)
        {
            Console.WriteLine("{0}: {1}", currentPosition++, powerShellObject.Members["title"].Value);
        }
    }
    catch (InvalidPowerShellStateException e)
    {
        Console.WriteLine(e);
    }

    Console.WriteLine("{0}Please press any key to continue...", Environment.NewLine);
    Console.ReadKey();
}

Auch dies ist an sich sehr simpel. Hier verwenden wir den StringBuilder, da String-Verkettungen nur über diesen geschehen sollen, aber das ist ein anderes Thema, natürlich kann das auch einfach durch „Stringappends“ geschehen oder aus einer Datei gelesen werden (oder wir geben einfach den Pfad zur Scriptdatei mit diesen Inhalt an). Weitere Informationen zur PowerShell-Scripterstellung kann der Microsoft Seite entnommen werden, siehe: http://technet.microsoft.com/de-de/scriptcenter/powershell.aspx