Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Geheimtipps für die Erstellung einer WPF-Anwendung in Windows PowerShell
Doug Finke
Windows PowerShell ermöglicht die nächste Stufe der Aufgabenautomatisierung. Alte Technologien werden dabei nicht verdrängt, sondern erweitert. Die Verwendung von Windows PowerShell (im Folgenden kurz als PowerShell bezeichnet) bedeutet nicht, dass Sie Ihre Anwendung neu aufbauen müssen, um die Vorteile nutzen zu können. Stattdessen können Sie PowerShell verwenden, um Ihre vorhandenen Ressourcen nahtlos zu integrieren und zu erweitern.
PowerShell ist eine Automatisierungstechnologie in Form einer Befehlszeilenschnittstelle, einer Skriptsprache und einer API.
In diesem Artikel stelle ich die wichtigsten PowerShell-Verfahren einzeln vor und erstelle einen Kapitalwertrechner (bit.ly/7oEij1) mit einer Windows Presentation Foundation (WPF)-GUI (siehe Abbildung 1).
Abbildung 1: PowerShell-Kapitalwertrechner
Ich möchte einige wichtige PowerShell-Elemente vorstellen: das WPF PowerShell Kit (WPK), die Objektpipeline, Funktionen, PSObjects mit Eigenschaften, nahtlose Integration in Microsoft .NET Framework, Module und mehr.
PowerShell basiert auf dem .NET Framework, sodass Sie problemlos auf das Framework zugreifen können, wie Sie es von anderen .NET-Sprachen gewohnt sind. Außerdem haben Sie Zugriff auf das restliche Windows-Betriebssystem und seine Komponenten, wie Dienste, Prozesse und Windows-Verwaltungsinstrumentation (WMI), sowie auf Remoteserver (die auch über PowerShell Version 2 verfügen und für die die Windows-Remoteverwaltung aktiviert ist).
Dies wird alles mit der neuen Skriptsprache ermöglicht, die von PowerShell verfügbar gemacht wird. Sie benötigen lediglich den Windows-Editor und einige PowerShell-Cmdlets (Aussprache: "command-lets"; ein Cmdlet ist ein einfacher Befehl, der in der PowerShell-Umgebung verwendet wird). Die gute Nachricht ist, dass diese Ressourcen zur Verwendung bereitstehen. Die Cmdlets sind in PowerShell integriert, und der Editor ist im Lieferumfang von Windows enthalten. Die drei Cmdlets sind: Das "Get-Help"-Cmdlet zeigt Informationen zu PowerShell-Befehlen und –Begriffen an. Mit dem "Get-Command"-Cmdlet werden grundlegende Informationen zu Cmdlets und anderen Elementen von PowerShell-Befehlen abgerufen. Über das "Get-Member"-Cmdlet werden die Elemente (Eigenschaften und Methoden) von Objekten abgerufen.
Es dreht sich alles um die Entdeckung von Funktionen, und diese Cmdlets unterstützen Sie beim Navigieren auf dieser neuen Plattform zum Automatisieren von Aufgaben.
Fangen wir also an.
Frage: Wie viele Codezeilen sind für die Erstellung einer WPF-Anwendung mit der Bezeichnung "Hello World" erforderlich?
Antwort: Zwei Zeilen, wenn Sie PowerShell und WPK verwenden, wie in Abbildung 2 gezeigt.
Abbildung 2: PowerShell-WPF-Anwendung bestehend aus zwei Zeilen
Dies ist eine vollständige WPF-Anwendung, die in PowerShell mit nur zwei Zeilen geschrieben wurde. In der ersten Zeile, "Import-Module WPK", wird das WPK-Paket mit einer Gruppe von PowerShell-Cmdlets importiert, die den Wrapper für WPF darstellen. Es ist interessant, dass Sie für die Erstellung weder Visual Studio, noch XAML oder C# benötigen. Sie müssen allerdings das WPK installieren (siehe nächsten Abschnitt).
PowerShell Version 2 ist bei Windows 7 und Windows Server 2008 R2 im Lieferumfang enthalten (und kann für ältere Windows-Systeme heruntergeladen werden). Das PowerShell Pack wurde zur gleichen Zeit wie die Client- und Serverbetriebssysteme veröffentlicht (als separater Download), einschließlich WPK. Es kann als Hommage an das beliebte Unix-Skripterstellungstool "Tcl/Tk" verstanden werden.
Ich beginne, indem ich die Anwendung von einem einfachen Satz von PowerShell-Variablen zu einer interaktiven WPF-Anwendung ausbaue. Dazu verwende ich die PowerShell Integrated Scripting Environment (ISE).
Möchten Sie die Schritte selbst verfolgen?
Wenn Sie Windows 7 verwenden, haben bereits fast alles, was Sie brauchen (PowerShell ist integriert).
Falls Sie Windows 7 nicht verwenden, müssen Sie PowerShell für ältere Betriebssysteme herunterladen und installieren. Achten Sie darauf, dass Sie den Download für das richtige Betriebssystem wählen. Weitere Informationen finden Sie im Windows Management Framework Core-Paket (bit.ly/9POYjq).
Unabhängig von der Version Ihres Betriebssystems müssen Sie das WPK herunterladen und installieren (bit.ly/dFVpfL). Es ist Teil des Windows 7 Resource Kit und enthält noch neun weitere PowerShell-Module, darunter ein ISE Pack zur Verwendung in der PowerShell ISE. Die ISE ist im Lieferumfang von PowerShell Version 2 enthalten. Das ISE Pack ist auch eine gute Schulungsressource, da veranschaulicht wird, wie die ISE auf verschiedenen Ebenen angepasst werden kann.
Führen Sie nach dem Starten von PowerShell dieses Cmdlet aus: Set-ExecutionPolicy RemoteSigned. Standardmäßig ist PowerShell so eingerichtet, dass keine Skripts ausgeführt werden. Dies ist eine Sicherheitsfunktion, die von PowerShell-Benutzern außer Kraft gesetzt werden kann bzw. muss. Damit "Set-ExecutionPolicy" funktioniert, müssen Sie über Administratorrechte verfügen und PowerShell explizit als Administrator ausführen, indem Sie mit der rechten Maustaste auf die PowerShell-Programmdatei klicken und die Option "Als Administrator ausführen" wählen.
Laden Sie die Skripts über den dazugehörigen Codedownload herunter, und entzippen Sie diese. Der einfachste Weg zur Ausführung der Anwendung ist die Ausführung in der ISE. Unter Windows 7 können Sie auf "Start" klicken und "ISE" eingeben. (Hinweis: Sie können PowerShell-Skripts – die über die Dateierweiterung ".ps1" verfügen – nicht per Doppelklick ausführen. Am einfachsten können Sie die Beispielskripts ausführen, indem Sie die ISE starten und die Option "Datei | Öffnen" verwenden, um die Skriptdatei zu öffnen.)
PowerShell 101
Ich werde einen Kapitalwertrechner erstellen. Dies ist eine einfache Formel, die in Abbildung 3 zu sehen ist.
Abbildung 3: Kapitalwertberechnung
In PowerShell beginnen Variablen mit dem Zeichen "$". In Zeile 7 verwende ich .NET Framework direkt, indem ich die statische "Pow"-Methode im "System.Math"-Namespace aufrufe. Mit der "Pow"-Methode wird das Ergebnis für eine angegebene Zahl zurückgegeben, die mit der zweiten angegebenen Zahl potenziert wurde. Die zum Aufrufen einer statischen .NET-Methode erforderliche Syntax umfasst die Klasse in Klammern gefolgt von zwei Doppelpunkten und dem Namen der Methode: [System.Math]::Pow(2,3). Falls Sie dies in der ISE ausführen, drücken Sie F5 (oder klicken Sie auf die Schaltfläche "Ausführen"), um die Ergebnisse im Ausgabebereich anzuzeigen. Sie können diesen Code auch kopieren und in die PowerShell-Befehlszeilenkonsole einfügen. Er wird ausgeführt, und das Ergebnis wird ausgegeben.
Dies ist ein guter Anfang, aber der Vorgang ist nicht ohne Weiteres wiederholbar. Ich könnte zwar immer neue Werte eingeben und dieses Skript ausführen, aber ich möchte es in anderen Skripts aufrufen können. Ich füge das Schlüsselwort function hinzu und ändere die Variablen in Parameter, damit ich die Ausgabe variieren und das Skript interaktiv machen kann (siehe Zeile 2 in Abbildung 4).
Abbildung 4: Erstellen einer PowerShell-Funktion
Hinzufügen des "function"-Schlüsselworts
Ich gebe der Funktion den Namen "Get-PresentValue". Es empfiehlt sich, beim Benennen von Funktionen die Verb-Nomen-Namenskonvention von PowerShell zu beachten. Dies ist beim Verwenden von PowerShell und bei der Entwicklungsarbeit dafür ein grundlegendes Konzept. Es sind vordefinierte "Verben" vorhanden, z. B. "Get", "Invoke", "New" und "Remove" (geben Sie "Get-Verb" ein, um die gesamte Liste anzuzeigen). Geben Sie "Get-Command" ein. Es werden alle Cmdlets (und mehr) zurückgegeben, die in der PowerShell-Sitzung definiert sind. Dies ist eine sehr lange Liste.
Das Erstellen einer Funktion ist so einfach wie das Eingeben von function Get-PresentValue {}. Von hier aus erstelle ich die Parameter mit Standardwerten und den Textkörper der Funktion, wie in Abbildung 4 dargestellt.
Wenn Sie Abbildung 3 mit Abbildung 4 vergleichen, sehen Sie, dass ich die Variablen – sowohl die Namen als auch die Werte – in eine einzelne Zeile transponiert und mit Kommas getrennt habe. Außerdem habe ich sie in Klammern gesetzt und nach dem Namen der Funktion angeordnet, sodass sie jeweils zu Parametern der Funktion werden. Diese Parameter verfügen jetzt über Standardwerte. Die Kapitelwertberechnung habe ich unverändert gelassen. Ein Hauptgrundsatz von PowerShell ist der "geringere Eingabeaufwand". In Zeile 3 in Abbildung 4 hätte ich die return-Anweisung verwenden können. Wenn Sie sie weglassen, bleibt das Verhalten gleich. Es kann jedoch vorkommen, dass Sie die "return"-Anweisung verwenden möchten, um den Fluss der Logik zu unterbrechen.
In diesem Beispiel zeige ich einige Möglichkeiten, wie Sie die "Get-PresentValue"-Funktion aufrufen können. Ohne Angabe von Parametern werden für alle Parameter Standardwerte verwendet. Parameter können entweder anhand der Position (siehe Zeile 8 in Abbildung 4) angegeben oder benannt werden (siehe Zeile 9). Ich empfehle Ihnen, sich in PowerShell-Parameter einzulesen. PowerShell unterstützt ein leistungsfähiges Modul für Parameterbindungen.
Ausblick: Ändern der "Get-PresentValue"-Funktion, um anstelle von einfachem Text ein .NET-Objekt zurückzugeben
PowerShell basiert auf .NET
Eine wichtige Innovation im Rahmen von PowerShell ist die Fähigkeit, Daten als vollständig typisierte Objekte zu übergeben. In Abbildung 5 wird das Konzept zur Erstellung eines PowerShell-Objekts, das Festlegen von Eigenschaften, das Zurückgeben des Objekts und das Nutzen des PowerShell-Moduls zum Ausdrucken veranschaulicht.
Abbildung 5: Zurückgeben vollständig typisierter Objekte aus PowerShell-Funktionen
In Zeile 6 verwende ich das "New-Object"-Cmdlet, mit dem eine Instanz eines .NET Framework-Objekts erstellt wird. Ich teile ihm den Typ des zu erstellenden Objekts mit (PSObject). Das Objekt ermöglicht eine einheitliche Anzeige von Objekten in der PowerShell-Umgebung. In Zeile 6 verwende ich außerdem den Parameter "–Property", für den eine Hashtabelle erforderlich ist. Die Kurzsyntax für Hashtabellen in PowerShell ist "@{}". Die in der Hashtabelle definierten Schlüssel-Wert-Paare – die im Parameter "–Property" übergeben werden – werden in Eigenschaften und Werte für das neue PSObject transformiert.
In Zeile 15 rufe ich schließlich die Funktion auf, und die Ergebnisse werden im Ausgabebereich angezeigt (in der ISE mit blauer Schattierung). Beachten Sie, dass PowerShell "weiß", wie das Objekt ausgegeben werden muss. Ich muss mich nicht darum kümmern, welche Eigenschaften ausgegeben werden müssen oder wie diese ausgegeben werden müssen. Dies ist eine der zentralen Stärken von PowerShell.
PowerShell-Bereiche und -Pipelines
Als Nächstes verwende ich PowerShell-Pipelines und stelle zwei weitere PowerShell-Cmdlets vor: "ForEach-Object" und "Format-Table" (siehe Abbildung 6).
Abbildung 6: PowerShell-Bereiche und -Pipelines
Der entscheidende Teil ist Zeile 13. Hier erhalten Sie erste Einblicke in die Flexibilität und die hohe Kompositionsqualität von PowerShell. Hier sind drei Abschnitte und zwei Pipes definiert. Im ersten Abschnitt wird der Bereichsoperator angezeigt (bestehend aus zwei Punkten), der zweite Abschnitt enthält "ForEach", und der letzte Abschnitt enthält "Format-Table". Ich werde jeden Abschnitt erläutern.
Erster Abschnitt, 1000..10101000..1010 steht für ein Array mit ganzen Zahlen von 1.000 bis 1.010 (einschließlich). PowerShell führt dafür bei Verfügbarkeit sofort einzelne Pushvorgänge in die Pipeline aus. PowerShell implementiert, wie Unix/Linux-basierte Shells, eine Pipeline, sodass die Ausgabe eines Cmdlets per Pipe als Eingabe für ein anderes Cmdlet ermöglicht wird. Bei PowerShell besteht die Pipeline aus .NET-Objekten. Aufgrund der Verwendung von Objekten ist es nicht erforderlich, eine willkürliche Textausgabe aus einem Befehl zum Extrahieren von Daten zu analysieren, da alle Objekte eine einheitliche Schnittstelle exportieren (siehe bit.ly/lVJarT).
Zweiter Abschnitt, ForEach { Get-PresentValue $_ } In diesem Abschnitt wird "ForEach" (auch als Alias "%") verwendet, wofür ein Skriptblock erforderlich ist. Stellen Sie sich einen Skriptblock als anonyme Methode vor (in anderen Sprachen auch als Lambda-Ausdrücke bezeichnet). Weitere Informationen hierzu finden Sie im Buch "PowerShell in Action, Second Edition" von Bruce Payette (Manning Publications, 2011).
"$_" ist eine automatische PowerShell-Variable und enthält das aktuelle Objekt in der Pipeline. Die ganzen Zahlen des Endergebnisses, ein Array mit zehn ganzen Zahlen, werden einzeln an "Get-PresentValue" übergeben. Weil wir den Parameter nicht benennen, übergebe ich ihn als Positionsparameter an "$Amount". Dies ist in Abbildung 6 im Ausgabebereich zu sehen.
Letzter Abschnitt, Format-Table "Format-Table" bewirkt das, was der Name schon sagt, nämlich das Formatieren der Ausgabe als Tabelle. Ich verwende den Parameter "-AutoSize", weil damit die Spaltengröße basierend auf der Breite der Daten angepasst wird.
Beachten Sie, dass ich die Iteration nicht über die Sammlung verwalte und dass PowerShell "weiß", welche Teile der über die Pipeline eingehenden Objekte in welcher Form gedruckt werden sollen. Dies führt dazu, dass Sie weniger Codezeilen schreiben und somit auch weniger Zeilen debuggen müssen. Da ich 90 Prozent meiner Zeit mit Debuggen und die restlichen 10 Prozent mit dem Schreiben von Bugs verbringe, ist dies für mich von Vorteil.
GUI-Zeit – 1. Runde
Es wird Zeit, dass wir das WPK verwenden. Mit dem Skript in Abbildung 7 wird die GUI in Abbildung 8 produziert. Ich habe den Parametern der "Get-PresentValue"-Funktion Typinformationen hinzugefügt (siehe Zeile 1 in Abbildung 7). Andere Personen, die diese Funktion nutzen, können so leicht erkennen, ob sie falsche Daten übergeben haben, z. B. Zeichenfolgen statt Zahlenwerte.
Abbildung 7: WPK "New-ListView"
Abbildung 8: Anzeige der GUI
Der wesentliche Teil des ursprünglichen Codes aus Abbildung 6 wurde beibehalten, und der Aufruf von "Get-PresentValue" wurde dem "DataContext" von "ListView" hinzugefügt. Dabei handelt es sich um ein WPF-Steuerelement, das die Infrastruktur zum Anzeigen einer Gruppe von Datenelementen bereitstellt. Die restlichen WPK-Elemente sind in die WPF-Datenbindung integriert und richten die Ansicht in "ListView" ein, damit die Daten angezeigt werden können.
Das WPK hält sich an den Hauptgrundsatz von PowerShell: die Verwendung des Verb-Nomen-Paars. Wenn ich also ein "Window"-, "Grid"-, "Canvas"- oder "ListBox"-Element erstellen möchte, füge ich einfach "New-" hinzu: "New-Window", "New-Grid", "New-Canvas" oder "New-ListBox" ("New" gilt hier als "Verb"). Diese Frameworkelemente sind dann bereit zur Verwendung.
Import-Module
Ein Modul ist ein Paket mit Elementen – z. B. Cmdlets, Skripts, Funktionen, Variablen und andere Tools und Dateien –, die in PowerShell verwendet werden können. Nachdem ein Modul importiert wurde, können Sie die Elemente des Moduls in der Sitzung verwenden. Wie bereits erwähnt, ist das WPK Teil des PowerShell Pack und enthält mehr als 700 PowerShell-Funktionen, die das Schichten einer WPF-GUI mit PowerShell als Grundlage vereinfachen.
Wenn man den herkömmlichen WPF-Hintergrund zugrunde legt, erscheinen die Zeilen 17 und 18 in Abbildung 7 ungewöhnlich. Das WPK unterstützt die Datenbindung, indem zwei Parameter verfügbar gemacht werden: "DataContext" und "DataBinding". Der Parameter "DataContext" erfordert einen Skriptblock. Ich übergebe hier also eine Zeile mit PowerShell-Code, mit deren Hilfe die zehn vorhandenen Kapitalwertobjekte aus Zeile 13 in Abbildung 6 erstellt werden. Als Nächstes richte ich die "ItemsSource"-Eigenschaft von "ListView", für die die Bindung erfolgen soll, in Zeile 18 ein. Der Parameter "DataBinding" erfordert eine Hashtabelle (beachten Sie "@{}"). Die Schlüssel sind die Namen der Eigenschaften des GUI-Objekts, für das die Bindung erfolgen soll.
Bei Verwendung des WPK müssen Sie weniger Code schreiben. Die "New-GridViewColumn"-Funktion erfordert eine Zeichenfolge, z. B. "Amount" (dies ist der Name einer Eigenschaft des Objekts, das von der "Get-PresentValue"-Funktion ausgegeben wird). Die Funktion legt die Zeichenfolge als "Header" fest und führt die Datenbindung automatisch für Sie durch.
Ich habe mit einer einfachen Funktion begonnen (Get-PresentValue) und am Ende die Ausgabe in Abbildung 8 erhalten. Dazu habe ich Parameter hinzugefügt, um die Wiederverwendbarkeit sicherzustellen, ein .NET PowerShell PSObject ausgegeben und die PowerShell-Objektpipeline und einen Bereichsoperator verwendet, um Kapitalwertelemente zu generieren. Anschließend habe ich das WPK importiert, die PowerShell-Objekte in den "DataContext" eines "ListView"-WPF-Steuerelements injiziert, die Bindung für den Parameter "ItemsSource" erstellt und die "ListView"-Ansicht mit Spaltennamen erstellt, die mit den Eigenschaftennamen des injizierten Objekts übereinstimmen. So habe ich eine einfache PowerShell/WPK-Kapitalwertanwendung erhalten. Das ist schön, aber hartcodiert.
Als Nächstes möchte ich mit dieser Anwendung interagieren, um sehen zu können, was mit meiner Investition passiert, wenn sich der Betrag, die Zinsen oder andere Parameter ändern.
GUI-Zeit – 2. Runde
Beim gegenwärtigen PowerShell/WPK-Skript muss ich die Parameter ändern, die Datei speichern und das Skript erneut ausführen, was nicht sehr komfortabel ist.
Ich werde die Anwendung überarbeiten, damit ich über die GUI fünf Parameter ändern und in "ListView" neue Werte anzeigen kann.
"New-Range"-Funktion Als Erstes möchte ich eine Funktion mit dem Namen "New-Range" hinzufügen (siehe Abbildung 9).
Abbildung 9: "New-Range"-Funktion
Mit dem von PowerShell bereitgestellten Bereichsoperator können Sie den Inkrementierungsgrad nicht variieren. Ich kann also nicht "(1..10 by 2)" angeben. Mit der "New-Range"-Funktion kann ich mein eigenes Inkrement angeben, sodass "New-Range 1 10 2" z. B. "1 3 5 7 9" ergibt.
Im nächsten Schritt arbeite ich die WPK-GUI aus, indem ich "New-ListView" per Wrapper in eine "New-Window"-Funktion einschließe. Wenn Sie "New-ListView" allein verwenden, bindet das WPK für Sie ein Fenster ein. Mit dem Angeben von "New-Window" habe ich eine bessere Kontrolle (siehe Abbildung 10).
Abbildung 10: "New-Window"-Funktion
Außerdem habe ich den "DataContext" aus "ListView" auf die "Window"-Umfangsebene angehoben und die neue "New-Range"-Funktion angewendet. Jetzt möchte ich fünf Textfelder, Beschriftungen und eine Schaltfläche hinzufügen. Auf diese Weise kann ich die Ausgabe von "Get-PresentValue" bei laufender Anwendung ändern. Zum Erstellen der erforderlichen Steuerelemente verwende ich die WPK-Funktionen "New-Grid", "New-Label", "New-TextBox" und "New-Button". Indem ich "New-Grid" zum Erstellen eines Rastersteuerelements verwende, kann ich beim Ändern der Fenstergröße und bei der Platzierung der Steuerelemente sehr flexibel vorgehen.
Für das Layout der GUI schachtele ich Raster in Rastern und Steuerelementen. Ich verwende weiterhin die Funktionen "New-Range" und "Get-PresentValue" im "DataContext", wie in Abbildung 11 in Zeile 2 zu sehen.
(Zum Vergrößern auf das Bild klicken)
Abbildung 11: "New-Grid"-Funktion
In den Zeilen 30 bis 37 in Abbildung 11 ist auch die "New-ListView"-Funktion weiterhin zu sehen. In Zeile 30 habe ich zwei zusätzliche Parameter hinzugefügt: "–Row" und "–Column". Damit wird "ListView" die Zeile und Spalte seiner Anordnung mitgeteilt (in der in Zeile 5 definierten "New-Grid"-Funktion). Die in Zeile 5 definierte "New-Grid"-Funktion nutzt die "Rows" und "Columns" zum Erstellen des Layouts für ein Raster. Ich möchte zwei Spalten mit einer Breite von 75 Pixel und drei Zeilen mit einer Höhe von 35 Pixel erstellen. Das Sternchen nach der zweiten "75" im Parameter "Rows" gibt an, dass der verfügbare Platz vollständig genutzt wird.
Nun ordne ich fünf Paare mit Beschriftungen und Textfeldern im Fenster an und teile den Steuerelementen mithilfe der Parameter "Row" und "Column" mit, in welchem Quadrant des Rasters sie verankert werden sollen. Außerdem gebe ich dem Textfeld einen Namen, damit ich später darauf zugreifen kann, vergebe mit dem Parameter "-Text" einen Standardwert und ordne die Steuerelemente über die Parameter "Margin" und "HorizontalAlignment" richtig an.
Zuletzt positioniere ich die Schaltfläche mithilfe der "New-Button"-Funktion im Raster. Beachten Sie, dass ich vor "Calculate" einen Unterstrich eingefügt habe. Auf diese Weise kann ich mit der Tastenkombination ALT+C auf die Schaltfläche zugreifen.
Der Kapitalwertrechner ist jetzt fast fertig. Ich muss das Klickereignis mit PowerShell-Code verknüpfen, die Werte in den Textfeldern lesen, diese als Parameter an "Get-PresentValue" übergeben und die Bindung an "ListView" einrichten.
"Do-Calculation"-Funktion
Ich werde eine "Do-Calculation"-Funktion hinzufügen, die einen einzelnen Parameter, "$window", erfordert (siehe Abbildung 12).
Abbildung 12: "Do-Calculation"-Funktion
Ich rufe "Do-Calculation" über die "-On-Click"-Eigenschaft von "New-Button" auf, die über den Inhalt "_Calculate" verfügt.
Die Verwendung von "Do-Calculation" ist einfach. Die Funktion erfasst die Informationen aller Textfelder, legt diese als PowerShell-Variablen fest und übergibt sie als Parameter an die Funktionen "New-Range" und "Get-PresentValue". Ich übergebe den Parameter "$window" (siehe Zeile 2 in Abbildung 13), der einen Verweis auf die in Abbildung 10 erstellte "New-Window"-Funktion enthält. Damit kann ich auf alle Eigenschaften des Fensters und auf die untergeordneten Steuerelemente zugreifen, speziell auf die Textfelder. Da ich jedem Textfeldsteuerelement einen Namen gegeben habe, kann ich für "$window" einen Pipevorgang zu "Get-ChildControl" durchführen und den Namen des Steuerelements übergeben und den Text über die ".Text"-Eigenschaft abrufen (siehe Zeilen 3 bis 7 in Abbildung 12).
(Zum Vergrößern auf das Bild klicken)
Abbildung 13: Fertiges Raster
Alle Details aus den Textfeldern werden erfasst, und ich lege "$window.DataContext" auf das Ergebnis von "New-Range" fest, das per Pipevorgang an "Get-PresentValue" übermittelt wird. Diese Funktion generiert ein Array mit PowerShell-Objekten, in dem die Ergebnisse von PresentValue-Berechnungen enthalten sind (siehe Zeilen 9 bis 12 in Abbildung 12).
In Abbildung 13 ist dargestellt, wie Sie das Klickereignis der Schaltfläche "Calculate" so verknüpfen, dass die "Do-Calculation"-Funktion aufgerufen und die Variable "$window" übergeben wird (siehe Zeilen 28 bis 29). Ich habe den Parameter "-On_Click" hinzugefügt, der einen Skriptblock erfordert. Darin rufe ich die "Do-Calculation"-Funktion auf und übergebe die Variable "$window", die für mich beim Verwenden der "New-Window"-Funktion erstellt wird. Jedes Mal, wenn ich auf die Schaltfläche klicke, wird die Bildschirmanzeige neu berechnet. Beachten Sie in Abbildung 13, dass ich auch Zeile 2 geändert habe, damit auch die "Do-Calculation"-Funktion aufgerufen wird.
Laden Sie die fertige Anwendung über die beigefügten Quellcodebeispiele herunter, um Einblick in das gesamte Skript zu erhalten.
Einfache, interaktive WPF-Anwendung
In diesem Artikel habe ich ein Skript mit weniger als 75 Codezeilen vorgestellt, das eine interaktive WPF-Anwendung ergibt, bei der die Schichtung mithilfe der Microsoft-Automatisierungsplattform "PowerShell" durchgeführt wird. PowerShell ist sowohl eine Skriptsprache als auch eine Befehlszeilenkonsole. Die enge Abstimmung auf .NET Framework und Windows eröffnet Ihnen interessante Möglichkeiten bei der Automatisierung. Zum Erlernen dieser neuen Plattform müssen Sie sicherlich Zeit investieren. Die gute Nachricht ist jedoch: Sie können sich zuerst mit den einfacheren Optionen beschäftigen, um die Produktivität zu steigern, und je nach Bedarf dann tiefer in die vielen Automatisierungsoptionen eintauchen, die PowerShell sowohl über Microsoft als auch über die allgemeine PowerShell-Community bietet.
Adhoc-Entwicklungsmodell und Ursprung von Windows PowerShell
Der Artikel von Doug Finke ist ein hervorragendes Beispiel für das Adhoc-Entwicklungsmodell. PowerShell unterscheidet sich in vielerlei Weise von anderen Programmiertechnologien: Schwerpunkt auf aufgabenorientierten Abstraktionen auf hoher Ebene, das adaptive Typsystem, mit dem unterschiedliche Typsysteme (.NET, Windows Management Instrumentation [WMI], XML, ADSI, ADO usw.) normalisiert werden und das Ihnen das Hinzufügen von Elementen zu Typen und Instanzen ermöglicht, das Datenflussmodul, mit dem ein Großteil des API-Impedance Mismatch-Codes überflüssig wird, den Entwickler schreiben müssen, sowie die Unterstützung für das Adhoc-Entwicklungsmodell.
Das Adhoc-Modell ist der Ausgangspunkt zur Lösung eines Problems mithilfe informeller Verfahren. Wenn Sie sich dafür entscheiden, es häufiger zu verwenden, können Sie es in ein informelles Skript konvertieren, und wenn Sie es freigeben möchten, können Sie es formeller gestalten. Als Ersteller von Tools fertigen wir häufig Tools für Benutzer mit unterschiedlichen Fähigkeiten an, sodass es wichtig ist, die Anforderungen und Erwartungen der gesamten Zielgruppe zu erfüllen. Meist ist dies mit der Bereitstellung einer GUI verbunden.
Der Artikel von Doug Finke beginnt mit einem namenlosen, hartcodierten Skript zum Berechnen des Kapitalwerts für einen bestimmten Geldbetrag, einen festen Zinssatz und eine Laufzeit. Er ändert dies dann in eine benannte Funktion mit benannten Parametern und Anfangswerten, für die ein einzelner Wert zurückgegeben wird. Als Nächstes wird ein Objekt zurückgegeben, damit die Bearbeitung durch andere Tools möglich wird. Schließlich wird daraus zuerst eine einfache GUI und dann eine umfangreichere GUI. Er investiert nur Code, wenn dies erforderlich ist, und jedes Skript fügt dem vorherigen kleine Inkremente hinzu. Am Ende gibt Doug Finke das Skript frei, sodass andere Benutzer das Tool verwenden und Vorschläge zu seiner Verbesserung machen können (z. B. "typisiert" er die Parameter nach einem entsprechenden Vorschlag, damit das Tool nicht abstürzt, falls Zeichenfolgen übergeben werden). Von Freigaben profitieren alle. Ich habe jetzt ein cooles Tool und schulde Doug Finke dafür Dank. Diese Schuld habe ich zum Teil beglichen, indem ich seinen Code durchgesehen und Vorschläge gemacht habe. Ich weiß schon recht viel über PowerShell und profitiere trotzdem in hohem Maße von den Vorschlägen der Community zu meinen Skripts. [Jeffrey Snover ist der Erfinder von Windows PowerShell und zusammen mit Bruce Payette und James Truher einer der Hauptdesigner. Weitere Informationen unterbit.ly/696Jor. – Ed.]
Das Adhoc-Entwicklungsmodell basiert auf der PowerShell-Zielsetzung, gleichzeitig eine hervorragende interaktive Shell und eine Skriptsprache zu bieten. Bruce Payette, einer der Sprachdesigner, hat einmal gesagt, dass die Lebensdauer von 99 Prozent von PowerShell-Skripten mit der Befehlseingabe beginnt und mit dem Wagenrücklaufzeichen endet. PowerShell unterstützt einen großen Bereich von Skriptstilen, von interaktiven Einzeilern an einer Eingabeaufforderung über Funktionen im Bash-Stil, die "$args" verwenden, bis hin zu formelleren Skripts, bei denen Parameter benannt, typisiert und mit Validierung, Datenbindung und Hilfeattributen versehen sind. Der Grund für die Wahl dieses Ansatzes beruht auf meinen vielen Jahren als Unix-Entwickler, in denen ich riesige Mengen von Shellskripts geschrieben habe. Als meine Skripts dann von Benutzern verwendet wurden und diese mehr Funktionen forderten, habe ich die Skripts verworfen und in Tcl oder Perl neu geschrieben. Häufig ist es dann passiert, dass ich auch diese neuen Skripts verworfen und alles in C noch einmal neu geschrieben habe. Mir wurde klar, dass – auch wenn unterschiedliche Probleme einen unterschiedlichen Grad an Formalismus und Leistung erfordern – es Wahnsinn war, dass es kein einzelnes Tool gab, mit dem ich diesen großen Bereich von Skripterstellungsanforderungen abdecken konnte. Benutzer könnten ihre Lernarbeit dann investieren, um zu einem Experten für dieses Tool zu werden, anstatt über gute Kenntnisse in vielen verschiedenen Tools verfügen zu müssen. Es hat eine Weile gedauert, aber ich habe dann ein Tool erstellt, das genau diese Anforderung erfüllt. Ich hoffe, Sie haben Spaß an der Verwendung von PowerShell.
– Jeffrey Snover, Distinguished Engineer und Lead Architect für Windows Server
Doug Finke*, Microsoft MVP für Windows PowerShell, ist Softwareentwickler bei Lab49. Sein Unternehmen erstellt professionelle Anwendungen für die Finanzdienstleistungsbranche. In den letzten 20 Jahren hat er als Entwickler und Autor gearbeitet und sich mit vielen unterschiedlichen Technologien beschäftigt. Weitere Informationen erhalten Sie über sein Blog, "Development in a Blink", unter dougfinke.com/blog.*
Unser Dank gilt den folgenden technischen Experten für die Durchsicht dieses Artikels: James Brundage, Sal Mangano, Sivabalan Muthukumar, Marco Shaw, Jeffrey Snover und Sylvain Whissell