Suchergebnisse für: powershell gui
Powershell GUI Programmierung für Dummies Step-by-Step
Ich habe ein Weilchen überlegt, ob ich eine Modulsammlung mit einfachen Befehlen schreibe, oder lieber die GUI-Programmierung erkläre. Da es jede Menge Codebeispiele im Internet gibt um auf die Schnelle das ein oder andere grafische Element zu erstellen, habe ich mich für die Erklärung entschieden, da dies wesentlich mehr Möglichkeiten zur eigenen Anpassung bietet. Für ganz Eilige habe ich ein Modul programmiert, welches ein paar grundsätzliche Funktionen bereit stellt. Die finden Sie am Ende des Artikels.
Grundgerüst
Grundsätzlich brauchen Sie in jedem grafischen Element folgenden Aufbau:
# Die ersten beiden Befehle holen sich die .NET-Erweiterungen (sog. Assemblys) für die grafische Gestaltung in den RAM.
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
# Die nächste Zeile erstellt aus der Formsbibliothek das Fensterobjekt.
$objForm = New-Object System.Windows.Forms.Form
# Die letzte Zeile sorgt dafür, dass unser Fensterobjekt auf dem Bildschirm angezeigt wird. Das muss immer am Ende stehen.
[void] $objForm.ShowDialog()
Zugegeben, dass ist nun wirklich nicht gerade weltbewegend, aber es soll einfach mal klar machen, was eben das Grundgerüst eines jeden GUI-Elements darstellt. Das [void] vor den .NET-Aufrufen sorgt dafür, dass Rückgabewerte aus dem .NET verschluckt werden. So wie wir es zurück bekommen würde es auch unser Script ausgeben und das wollen wir normaler Weise nicht (insbesondere wenn Sie Ihre GUI-Elemente als Funktion verpacken)!
Position und Größe festlegen
Alle weiteren Befehle tragen Sie in Ihr Script bitte nach der grün gekennzeichneten Zeile ein, da diese Zeile das Fensterobjekt erstellt und alle weiteren Codeschnippsel unser Hauptfenster anpassen. Sind unsere Anpassungen abgeschlossen, sorgen wir mit der blauen Zeile für die Anzeige unseres fertigen Objekts. Die Zeile mit der Eigenschaft Startposition legt fest, wo auf dem Bildschirm unser Fenster auftauchen soll.
$objForm.StartPosition = "CenterScreen"
Wenn Sie auf $objForm ein get-member folgen lassen, also $objForm | gm in einer Zeile nach der grünen, dann sehen Sie die gesamten Events, Methoden und Eigenschaften, die Sie mit dem Fenster verwenden können. Dort werden Sie auch die Eigenschaft (Property) StartPosition finden. In der rechten Spalte sehen Sie dann die Objektklasse System.Windows.Forms.FormStartPosition welche die Funktionen bereit stellt. Vielleicht haben Sie sich auch gefragt welche Werte Sie sonst noch verfüttern können außer CenterScreen. Sorry, aber ich kenne auch nicht das komplette .NET-Framework auswendig, also fragen wir doch einfach die Powershell mittels der Klasse System.Enum in Form von:
[System.Enum]::GetNames("System.Windows.Forms.FormStartPosition")
Das müssen Sie gar nicht im Script eintippen, sondern das können Sie ganz normal in die Konsole eintippen. Leider funktioniert dies nicht bei allem Objekteigenschaften, sondern nur bei denen mit Stichworten. Aber das ist besser als nichts. Eine detaillierte Erklärung der einzelnen Werte von Eigenschaft finden Sie bei MSDN. Googeln Sie einfach nach der .NET-Klasse, also beispielsweise: System.Windows.Forms.FormStartPosition und klicken Sie auf den Link bei dem in der URL MSDN mit drin steht.
Die Cleveren unter Ihnen haben sich bestimmt schon gefragt, warum das Assembly System.Drawing geladen wird, da das obere Beispiel auch ohne die Zeile mit dem DrawingAssembly funktioniert. Das Drawing Assembly ermöglicht uns Position (dazu später mehr) und Größe der grafischen Elemente zu bestimmen. Die Größe ist nämlich ein eigenes Unterobjekt von unserem Fenster. So ähnlich wie am „Objekt“ Mensch auch Unterobjekte wie Arme und Beine dran sind. $objForm ist also unser Fenster und der Eigenschaft Size erzeugen wir nun ein eigenes Objekt, das für die Verwaltung der Größe zuständig ist. In diesem Fall ist unser Fenster in der Ausgangsversion also 300 Bildpunkt breit und 200 Bildpunkte hoch.
$objForm.Size = New-Object System.Drawing.Size(300,200)
Das Fenster können Sie wie ein übliches Anwendungsfenster nun auch kleiner oder größer ziehen oder durch festhalten der Titelleiste die positionieren. Die Fensterknöpfe zum Minimieren (in die Taskleiste) und Maximieren als auch zum schließen funktionieren auch bereits, ohne dass Sie dafür etwas hätten tun müssen. Aber das das mit dem Schließen funktioniert haben Sie bestimmt sowieso schon herausgefunden. 😉
Titelleiste
Die Titelleiste beschriften können Sie mit:
$objForm.Text = "Überschrift"
Textinhalt
Um einen Text ins Fenster hinein zu schreiben brauchen wir die Objektklasse Label aus dem Forms Assembly.
$objLabel = New-Object System.Windows.Forms.Label $objLabel.Location = New-Object System.Drawing.Size(10,50) $objLabel.Size = New-Object System.Drawing.Size(100,20) $objLabel.Text = "Hallo Welt" $objLabel.Name = "Hallo Welt" $objForm.Controls.Add($objLabel)
In der ersten Zeile wird ein neues Objekt aus der Objektklasse Label erstellt. Dies hat mit unserem Hauptfenster an dieser Stelle noch gar nichts zu tun!
In der zweiten Zeile greifen wir nun wieder in das Drawingsassembly und erstellen ein Objekt Location und kleben das an unser Labelobjekt dran. Durch die Werte 10 und 50 wird ein Offset festgelegt um wie viele Bildschirmpunkte das Label später bei der Anzeige nach rechts (10 Punkte) und nach unten (50 Punkte) versetzt angezeigt werden soll.
In der dritten Zeile kleben Sie in ähnlicher Form nun das Objekt Size an unseren Text. Damit reservieren Sie die Größe Ihrer Textbox. Sollte Ihr Text nicht komplett angezeigt werden kann dies daran liegen, dass der Bereich den Sie reserviert haben nicht groß genug für die Anzeige ist. Hier wurden 100 Bildpunkte horizontal und 20 Bildpunkte vertikal vorgegeben.
In der vierten Zeile legen Sie dann endlich den darzustellenden Text fest. Der kann natürlich auch gerne in Form einer Variablen übergeben werden.
In der fünften Zeile geben Sie dem Objekt einen Namen. Das könnte in diesem Beispiel auch entfallen, aber wenn man aus anderen Programmteilen später darauf zurückgreifen möchte, ist es immer gut einen Namen festzulegen.
In der letzten Zeile wird nun unser Labelobjekt ($objLabel) in unser Hauptfenster ($objForm) eingebaut.
Wenn Sie sich verwundern, warum die Positionen und Größen im Beispiel so seltsam sind, machen Sie doch gleich eine kleine Übung mit eigenen Texten und rücken Sie sich alles schön zurecht.
Buttons
Dann wollen wir doch noch einen Knopf annähen?!
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"
$OKButton.Name = "OK"
$OKButton.DialogResult = "OK"
$OKButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($OKButton)
Die ersten fünf Zeilen sind denen aus dem Beispiel Textinhalt ähnlich. Daher nur die Information, dass wir hier auf die Objektklasse Button zurückgreifen um einen Knopf zu erstellen. Wer hätte das gedacht? 😉
Erklärungsbedürftig ist dafür dann Zeile 5+6! In Zeile 5 geben Sie den Wert an, der dem aufrufenden Objekt bei einem Klick zurück geliefert werden soll. Nach einm Klick auf einen Knopf wird dann der beim Knopf gesetzte Wert von DialogResult in die Eigenschaft Dialogresult von $objForm geschrieben.
Wenn Sie auf $OKButton oder $objForm ein get-member absetzen finden Sie bei beiden den Event Click. Sie können also nicht nur auf den Knopf, sondern auch am Fenster insgesamt abfragen, ob man es angeklickt hat. Bleiben wir bei unserem Knopf! Um den Knopf mit einer Funktion auszustatten kleben Sie noch das Click Ereignis an den Knopf dran (Zeile 6). Selbstverständlich gehen auch die anderen Events wie MouseDoubleClick, Mousehover, MouseLeave, etc… was auch immer Sie vorhaben. Grundsätzlich passiert dies durch $OKButton.Add_Click({}). In den Klammern steht dann Ihr Powershellscriptcode den Sie ausführen möchten, wenn der Knopf angeklickt wurde. Im Beispiel steht in der geschweiften Klammer $objForm.Close(). Durch $objForm.Close() schließen Sie das Hauptfenster.
In der letzten Zeile wird der Knopf an das Hauptfenster geklebt.
Wenn Sie nun ganz am Ende des Scripts, also nach dem ShowDialog einfach $objForm.DialogResult hinten dran schreiben, wird der Text den Sie bei $OKButton.DialogResult bei anklicken zugewiesen haben auf der Konsole ausgegeben. Natürlich können Sie mit $OKButton.DialogResult auch alles andere anstellen. Es ist ja „einfach nur eine Textvariable“. Falls Sie größere Codeabschnitte beim anklicken ausführen möchten können Sie natürlich auch entweder über Funktionen arbeiten, oder es so schreiben:
$OKButton.Add_Click({ # ....weiterer Code })
So, nun haben Sie einen OK-Knopf! Wie wäre es, wenn Sie den Code-Abschnitt des OK-Knopfes einfach noch ein 2. Mal unter den OKButton kopieren, die Zahlen für die Positionierung anpassen und die Variable $OKButton durch $CancelButton im kopierten Abschnitt ersetzen. Schon haben Sie zwei Knöpfchen. Auch der Code, der durch Klick auf den CancelButton ausgeführt wird sollte angepasst werden, damit unterschiedliche Werte für $objForm.DialogResult zurück geliefert werden, je nachdem was angeklickt wird.
Sollen die beiden Knöpfe nun auch bei Enter (= OK) oder Escape (= Cancel) ausgelöst werden bietet sich folgendes an:
$objForm.KeyPreview = $True $objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") { $ObjForm.DialogResult="OK";$objForm.Close()} }) $objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") { $ObjForm.DialogResult="Cancel";$objForm.Close()} })
Hier wird der KeyDown Event noch an Ihr Fenster montiert. Wird dann bei ausgelöstem Keydown Ereignis (if $_.KeyCode -eq „Enter“) Enter gedrückt, wird in $ObjForm.DialogResult wieder „OK geklickt“ rein geschrieben und falls die gedrückte Taste „Escape“ (ESC) ist (if $_.KeyCode -eq „Escape“) dann kommt eben „Cancel geklickt“ in $ObjForm.DialogResult. Bei beiden Knöpfen wird auch noch das Fenster geschlossen durch $objForm.Close(). $objForm.KeyPreview = $True müssen immer mit dazu schreiben, sonst klappt das eher schlecht als recht.
Texteingabefeld
Möchten Sie Texte oder Zahlen vom Benutzer abfragen, können Sie das natürlich auch über benutzerfreundliche Fenster tun. Alles was Sie dazu brauchen ist folgender Code in dem o.a. Grundgerüst:
$objTextBox = New-Object System.Windows.Forms.TextBox $objTextBox.Location = New-Object System.Drawing.Size(10,100) $objTextBox.Size = New-Object System.Drawing.Size(100,20) $objForm.Controls.Add($objTextBox)
Damit bauen Sie sich ein Eingabefeld dazu. Eine Erklärung ist hier wohl überflüssig, was die einzelnen Zeilen bedeuten. Schön, dass wir nun ein Eingabefeld haben, aber wo wird das, was der Benutzer eingetippt hat hinterlegt? In:
$objTextBox.Text
Wenn Sie bei dem ScriptBlock für das Eingabefeld die Zeile:
$objTextBox.Text = "Vorgabe"
ergänzen, können Sie schon einen Standardtext vor belegen lassen. Das komplette Script könnte also aktuell etwa so aussehen:
[void] [System.Reflection.Assembly]::LoadWithPartialName(„System.Drawing“)
[void] [System.Reflection.Assembly]::LoadWithPartialName(„System.Windows.Forms“)
$objForm = New-Object System.Windows.Forms.Form
$objForm.Text = „Dateneingabe“
$objForm.Size = New-Object System.Drawing.Size(400,300)
$objForm.StartPosition = „CenterScreen“
$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq „Enter“) { $objForm.DialogResult=“OK“;$objForm.Close()} })
$objForm.Add_KeyDown({if ($_.KeyCode -eq „Escape“) { $objForm.DialogResult=“Cancel“;$objForm.Close()} })
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = „OK“
$OKButton.DialogResult = „OK“
$OKButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($OKButton)
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = „Cancel“
$CancelButton.DialogResult = „Cancel“
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20)
$objLabel.Size = New-Object System.Drawing.Size(280,20)
$objLabel.Text = „Bitte geben Sie etwas ein:“
$objForm.Controls.Add($objLabel)
$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(10,40)
$objTextBox.Size = New-Object System.Drawing.Size(260,20)
$objTextBox.Text = „Vorgabe“
$objForm.Controls.Add($objTextBox)
[void] $objForm.ShowDialog()
If ($objForm.DialogResult -like „OK“) {$objTextBox.Text} else {„Abbruch geklickt“}
Auf dieselbe Art und Weise können Sie auch mehrere Textbereiche einfügen. Genauso wie mit den Knöpfen.
Auswahlliste
Wie wäre es mit einer Auswahlliste? Hier sind die Grundlagen wieder identisch. Im vollständigen nachfolgenden Script sind die Besonderheiten der Listbox orange hervorgehoben:
$x = @()
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$objForm = New-Object System.Windows.Forms.Form $objForm.Text = "Data Entry Form" $objForm.Size = New-Object System.Drawing.Size(300,200) $objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True $objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") { foreach ($objItem in $objListbox.SelectedItems) {$x += $objItem} $objForm.Close() } })
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") {$objForm.Close()}})
$OKButton = New-Object System.Windows.Forms.Button $OKButton.Location = New-Object System.Drawing.Size(75,120) $OKButton.Size = New-Object System.Drawing.Size(75,23) $OKButton.Text = "OK"
$OKButton.Add_Click( { foreach ($objItem in $objListbox.SelectedItems) {$x += $objItem} $objForm.Close() })
$objForm.Controls.Add($OKButton)
$CancelButton = New-Object System.Windows.Forms.Button $CancelButton.Location = New-Object System.Drawing.Size(150,120) $CancelButton.Size = New-Object System.Drawing.Size(75,23) $CancelButton.Text = "Cancel" $CancelButton.Add_Click({$objForm.Close()}) $objForm.Controls.Add($CancelButton)
$objLabel = New-Object System.Windows.Forms.Label $objLabel.Location = New-Object System.Drawing.Size(10,20) $objLabel.Size = New-Object System.Drawing.Size(280,20) $objLabel.Text = "Suchen Sie sich etwas aus:" $objForm.Controls.Add($objLabel)
$objListbox = New-Object System.Windows.Forms.Listbox $objListbox.Location = New-Object System.Drawing.Size(10,40) $objListbox.Size = New-Object System.Drawing.Size(260,20) $objListbox.SelectionMode = "MultiExtended"
[void] $objListbox.Items.Add("1. Element") [void] $objListbox.Items.Add("2. Element") [void] $objListbox.Items.Add("3. Element") [void] $objListbox.Items.Add("4. Element") [void] $objListbox.Items.Add("5. Element")
$objListbox.Height = 70 $objForm.Controls.Add($objListbox)
[void] $objForm.ShowDialog()
$x
1. orange Zeile: $x wird hier als Array und nicht als String definiert, da unter Umständen es mehrere Elemente die angeklickt (mit Strg-Taste) wurden übergeben muss.
Darauf folgen 2 orange Codeabschnitte, die identisch sind. Der erste enthält die Reaktion für das Drücken der Enter-Taste, der zweite die Reaktion für einen Klick auf den OK-Knopf. Da bei beiden Aktionen dasselbe stattfinden soll steht natürlich auch derselbe Inhalt drin. Die Erklärung hierfür möchte ich aber erst einmal hinten anstellen und zunächst den 3. orangen Codeabschnitt erklären in dem das Auswahlfeld zusammen gebaut wird.
Auch hier erstellen wir uns in der 1. Zeile aus dem Windows.Forms Assembly zunächst das ListBox Objekt. Aus Zeile 2. und 3. Size und Location sollte an dieser Stelle klar sein (siehe weiter oben).
In Zeile 4 finden wir den sog. SelectionMode. Damit können Sie festlegen, ob mehrere Elemente oder nur eines ausgewählt werden können. Welche weiteren Alternativen außer MultiExtended noch zur Verfügung können Sie wieder über die Klasse System.Enum herausfinden (weiter oben beschrieben).
In den darauf folgenden Zeilen werden die einzelnen darzustellenden Elemente hinzugefügt. Selbstverständlich können Sie anstatt den darzustellenden Text direkt einzugeben auch Variablen übergeben. Dann aber bitte nur die Klammern, ohne die Anführungszeichen! Eleganter wäre in der Form vielleicht eine Schleife gewesen. Das können Sie ja als kleine Übung betrachten. 😉
Listbox.Height legt die vertikale Größe der Listbox fest. Eigentlich passiert das doch durch die Size Anweisung aus dem Drawing-Assembly?! Kommentieren Sie die Zeile doch einfach einmal aus und starten Sie das Script. Das ist bestimmt eine interessante Überraschung!
Zu guter Letzt wird unsere Listbox ins Fenster geschraubt.
So, nun zu dem was passiert, wenn OK geklickt, oder Enter gedrückt wird. Zunächst einmal wird eine foreach-Schleife angelegt, die so lange durchlaufen wird, wie es ausgewählte Elemente gibt. In $objListbox.SelectedItems sind alle ausgewählten Elemente enthalten. Diese werden dann der Reihe nach bei jedem Schleifendruchlauf zu $objItem. Im Schleifenrumpf werden dann die Werte in den Array $x eingespeist. Sind alle Elemte in den Array überführt ist die Schleife zu Ende und es wird $objForm.Close() ausgeführt, was das Fenster schließt.
Am Ende des Scripts wird dann wieder $x als Rückgabewert mit den ausgewählten Elementen ausgegeben.
Dropdownfeld
Ein Dropdownfeld oder auch Combox genannt funktioniert ähnlich wie die Auswahlliste. Sie müssen lediglich die Zeile mit „MultiExtended“ entfernen (eine Mehrfachauswahl wird vom Dropdownfeld nicht unterstützt), den Begriff Listbox gegen Combobox tauschen und bei den selected-items Einträgen das s am Schluß entfernen. Also ist es eigentlich sogar einfacher als die Auswahlliste. Hier das komplette Script:
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$objForm = New-Object System.Windows.Forms.Form $objForm.Text = "Combobox" $objForm.Size = New-Object System.Drawing.Size(300,200) $objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter") { foreach ($objItem in $objCombobox.SelectedItem) {$x += $objItem} $objForm.Close() } })
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") {$objForm.Close()}})
$OKButton = New-Object System.Windows.Forms.Button $OKButton.Location = New-Object System.Drawing.Size(75,120) $OKButton.Size = New-Object System.Drawing.Size(75,23) $OKButton.Text = "OK"
$OKButton.Add_Click( { foreach ($objItem in $objCombobox.SelectedItem) {$x += $objItem} $objForm.Close() })
$objForm.Controls.Add($OKButton)
$CancelButton = New-Object System.Windows.Forms.Button $CancelButton.Location = New-Object System.Drawing.Size(150,120) $CancelButton.Size = New-Object System.Drawing.Size(75,23) $CancelButton.Text = "Cancel" $CancelButton.Add_Click({$objForm.Close()}) $objForm.Controls.Add($CancelButton)
$objLabel = New-Object System.Windows.Forms.Label $objLabel.Location = New-Object System.Drawing.Size(10,20) $objLabel.Size = New-Object System.Drawing.Size(280,20) $objLabel.Text = "Treffen Sie bitte eine Auswahl:" $objForm.Controls.Add($objLabel)
$objCombobox = New-Object System.Windows.Forms.Combobox $objCombobox.Location = New-Object System.Drawing.Size(10,40) $objCombobox.Size = New-Object System.Drawing.Size(260,20)
[void] $objCombobox.Items.Add("Item 1") [void] $objCombobox.Items.Add("Item 2") [void] $objCombobox.Items.Add("Item 3") [void] $objCombobox.Items.Add("Item 4") [void] $objCombobox.Items.Add("Item 5")
$objCombobox.Height = 70 $objForm.Controls.Add($objCombobox) $objForm.Topmost = $True
$objForm.Add_Shown({$objForm.Activate()}) [void] $objForm.ShowDialog()
$x
Kalenderauswahl
Benutzer nach einem Datum fragen ist eine Kunst für sich! Da kann man tausend Beispiele schreiben wie das Datum einzugeben ist und trotzdem machen sie es falsch. Abgesehen davon hat man die Probleme mit Schaltjahren und sonstigem Brimbamborium rund um die Datumsverwaltung. Obendrein müsste man den Text erst in ein Datumsformat konvertieren. Das ist alles gaaaanz gruselig. Also machen wir es uns einfach!
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$objForm = New-Object Windows.Forms.Form $objForm.Text = "Wählen Sie ein Datum aus" $objForm.Size = New-Object System.Drawing.Size (190,200) $objForm.StartPosition = "CenterScreen"
$objForm.KeyPreview = $True $objForm.Add_KeyDown({
if ($_.KeyCode -eq "Enter")
{
$WahlDatum=$objCalendar.SelectionStart
$objForm.Close()
}
})
$objForm.Add_KeyDown({ if ($_.KeyCode -eq "Escape") { $objForm.Close() } })
$objCalendar = New-Object System.Windows.Forms.MonthCalendar $objCalendar.ShowTodayCircle = $False $objCalendar.MaxSelectionCount = 1 $objForm.Controls.Add($objCalendar)
[void] $objForm.ShowDialog()
if ($WahlDatum) { Write-Host "Ausgewähltes Datum: $WahlDatum" }
Fertig ist der Kalender! Auch hier habe die neuen Stellen wieder orange markiert. Der Einfachheit halber sind keine OK oder Cancel-Buttons eingebaut. Es reagiert nur auf Enter oder ESC. Diese Funktion können Sie aber gerne als kleine Vertiefung nachrüsten. 😉
Die erste eingefärbte Zeile holt aus dem Kalenderobjekt (das wir weiter unten erstellen) das ausgewählte Datum ab und schreibt es in die Variable $WahlDatum. Das drumherum sollten Sie erkennen. Es sorgt dafür, dass dies nur passiert, wenn jemand Enter gedrückt hat.
Im nach folgenden Block wird das Kalenderobjekt erzeugt und eingestellt. ShowTodayCircle=$False blendet nur ein hässliches Viereck aus. MaxSelectionCount=1 sorgt dafür, dass nur ein Datum abgeholt wird. Der Rest des Blocks sollte klar sein.
Am Ende wird nur dann ein Datum zurückgegeben, wenn auch eins ausgewählt wurde.
Baumansicht
Die sog. Baumansicht oder auch Treeview genannt läßt sich auch recht einfach implementieren:
[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null [reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
$form1 = New-Object System.Windows.Forms.Form $treeView1 = New-Object System.Windows.Forms.TreeView $InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState $form1.Text = "Überschrift" $form1.Name = "form1" $form1.DataBindings.DefaultDataSourceUpdateMode = 0 $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 284 $System_Drawing_Size.Height = 262 $form1.ClientSize = $System_Drawing_Size
$System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 260 $System_Drawing_Size.Height = 238 $treeView1.Size = $System_Drawing_Size $treeView1.Name = "treeView1" $System_Windows_Forms_TreeNode_1 = New-Object System.Windows.Forms.TreeNode $System_Windows_Forms_TreeNode_2 = New-Object System.Windows.Forms.TreeNode $System_Windows_Forms_TreeNode_3 = New-Object System.Windows.Forms.TreeNode $System_Windows_Forms_TreeNode_3.Text = "SubSub" $System_Windows_Forms_TreeNode_3.Name = "Knoten2"
$System_Windows_Forms_TreeNode_2.Nodes.Add($System_Windows_Forms_TreeNode_3)|Out-Null $System_Windows_Forms_TreeNode_2.Text = "SubA" $System_Windows_Forms_TreeNode_2.Name = "Knoten1"
$System_Windows_Forms_TreeNode_1.Nodes.Add($System_Windows_Forms_TreeNode_2)|Out-Null $System_Windows_Forms_TreeNode_4 = New-Object System.Windows.Forms.TreeNode $System_Windows_Forms_TreeNode_4.Text = "SubB" $System_Windows_Forms_TreeNode_4.Name = "Knoten3"
$System_Windows_Forms_TreeNode_1.Nodes.Add($System_Windows_Forms_TreeNode_4)|Out-Null $System_Windows_Forms_TreeNode_5 = New-Object System.Windows.Forms.TreeNode $System_Windows_Forms_TreeNode_5.Text = "SubC" $System_Windows_Forms_TreeNode_5.Name = "Knoten4"
$System_Windows_Forms_TreeNode_1.Nodes.Add($System_Windows_Forms_TreeNode_5)|Out-Null $System_Windows_Forms_TreeNode_1.Text = "SubB" $System_Windows_Forms_TreeNode_1.Name = "Knoten0"
$treeView1.Nodes.Add($System_Windows_Forms_TreeNode_1)|Out-Null $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 12 $System_Drawing_Point.Y = 12 $treeView1.Location = $System_Drawing_Point $treeView1.DataBindings.DefaultDataSourceUpdateMode = 0 $treeView1.TabIndex = 0 $form1.Controls.Add($treeView1)
$InitialFormWindowState = $form1.WindowState $form1.add_Load($OnLoadForm_StateCorrection) $form1.ShowDialog()| Out-Null
$treeView1.SelectedNode
Sollten Sie noch eine Erklärung benötigen hinterlassen Sie doch einen Kommentar.
Statusleiste und Karteikartenreiter
Hier noch ein kleines Beispiel für Karteikartenreiter und eine Statusleiste. Erklärung durch Kommentarzeilen im Script:
[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null [reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
$form1 = New-Object System.Windows.Forms.Form $statusBar1 = New-Object System.Windows.Forms.StatusBar $tabControl1 = New-Object System.Windows.Forms.TabControl $tabPage1 = New-Object System.Windows.Forms.TabPage $comboBox1 = New-Object System.Windows.Forms.ComboBox $tabPage2 = New-Object System.Windows.Forms.TabPage $button1 = New-Object System.Windows.Forms.Button
$form1.Text = "Reiter und Statusleiste" $form1.Name = "form1" $form1.DataBindings.DefaultDataSourceUpdateMode = 0 $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 284 $System_Drawing_Size.Height = 262 $form1.ClientSize = $System_Drawing_Size
# Statusleiste anlegen und mit Ausgangswert (Text) belegen $statusBar1.Name = "statusBar1" $statusBar1.Text = "Auswahl: Noch nicht getroffen" $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 284 $System_Drawing_Size.Height = 22 $statusBar1.Size = $System_Drawing_Size $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 0 $System_Drawing_Point.Y = 240 $statusBar1.Location = $System_Drawing_Point $statusBar1.DataBindings.DefaultDataSourceUpdateMode = 0 $statusBar1.TabIndex = 1 $form1.Controls.Add($statusBar1)
# Auswahlreiter anlegen $tabControl1.TabIndex = 0 $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 228 $System_Drawing_Size.Height = 162 $tabControl1.Size = $System_Drawing_Size $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 23 $System_Drawing_Point.Y = 35 $tabControl1.Location = $System_Drawing_Point $tabControl1.DataBindings.DefaultDataSourceUpdateMode = 0 $tabControl1.Name = "tabControl1" $tabControl1.SelectedIndex = 0 $form1.Controls.Add($tabControl1)
# Auswahl Seite anlegen und an Auswahlreiter binden $tabPage1.TabIndex = 0 $tabPage1.UseVisualStyleBackColor = $True $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 220 $System_Drawing_Size.Height = 136 $tabPage1.Size = $System_Drawing_Size $tabPage1.Text = "Auswahlreiter" $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 4 $System_Drawing_Point.Y = 22 $tabPage1.Location = $System_Drawing_Point $System_Windows_Forms_Padding = New-Object System.Windows.Forms.Padding $System_Windows_Forms_Padding.All = 3 $System_Windows_Forms_Padding.Bottom = 3 $System_Windows_Forms_Padding.Left = 3 $System_Windows_Forms_Padding.Right = 3 $System_Windows_Forms_Padding.Top = 3 $tabPage1.Padding = $System_Windows_Forms_Padding $tabPage1.Name = "tabPage1" $tabPage1.DataBindings.DefaultDataSourceUpdateMode = 0 $tabControl1.Controls.Add($tabPage1)
# ComboBox auf Auswahltabseite kleben $comboBox1.FormattingEnabled = $True $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 121 $System_Drawing_Size.Height = 21 $comboBox1.Size = $System_Drawing_Size $comboBox1.DataBindings.DefaultDataSourceUpdateMode = 0 $comboBox1.Name = "comboBox1" $comboBox1.Items.Add("Eins")|Out-Null $comboBox1.Items.Add("Zwei")|Out-Null $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 18 $System_Drawing_Point.Y = 29 $comboBox1.Location = $System_Drawing_Point $comboBox1.TabIndex = 0 $comboBox1.add_DropDownClosed({$statusBar1.Text = "Auswahl: "+$comboBox1.SelectedItem}) $tabPage1.Controls.Add($comboBox1)
# Beendenreiter anlegen $tabPage2.TabIndex = 1 $tabPage2.UseVisualStyleBackColor = $True $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 220 $System_Drawing_Size.Height = 136 $tabPage2.Size = $System_Drawing_Size $tabPage2.Text = "Beenden" $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 4 $System_Drawing_Point.Y = 22 $tabPage2.Location = $System_Drawing_Point $System_Windows_Forms_Padding = New-Object System.Windows.Forms.Padding $System_Windows_Forms_Padding.All = 3 $System_Windows_Forms_Padding.Bottom = 3 $System_Windows_Forms_Padding.Left = 3 $System_Windows_Forms_Padding.Right = 3 $System_Windows_Forms_Padding.Top = 3 $tabPage2.Padding = $System_Windows_Forms_Padding $tabPage2.Name = "tabPage2" $tabPage2.DataBindings.DefaultDataSourceUpdateMode = 0 $tabControl1.Controls.Add($tabPage2)
# Beenden Seite anlegen und an Beendenreiter binden $button1.TabIndex = 0 $button1.Name = "button1" $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 75 $System_Drawing_Size.Height = 23 $button1.Size = $System_Drawing_Size $button1.UseVisualStyleBackColor = $True $button1.Text = "Fertig" $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 28 $System_Drawing_Point.Y = 51 $button1.Location = $System_Drawing_Point $button1.DataBindings.DefaultDataSourceUpdateMode = 0 $button1.add_Click({$form1.close();write-host $comboBox1.SelectedItem}) $tabPage2.Controls.Add($button1)
# Fenster anzeigen $form1.ShowDialog()| Out-Null
Anregungen
Weiter oben hatte ich schon einmal erwähnt, dass man mit get-member ganz interessante Dinge über die Objekte herausfinden kann. Wenn Sie in Ihr Script z.B. bei dem Objekt $objForm | get-memeber einfügen werden Sie feststellen, dass man auch die Eigenschaften Fore- und Backcolor einstellen kann. Schreiben Sie doch einfach mal eine Zeile wie $objForm.Backcolor=“Yellow“ in Ihr Script. Welche Farben gibt’s? Nun, das ist doch sicher eine begrenzte Liste an Farben…Aus welcher Objektklasse die Farbe bereit gestellt wird steht beim get-member ja in der rechten Spalte. Ja, richtig! Da steht System.Drawing.Color als Objektklasse. Wie wäre es nun mit einem [System.Enum]::GetNames(„System.Drawing.Color“)? Schwupps…schon wissen Sie welche Farben Sie einstellen können. Ein Farbauswahlbox gibt es auch schon fertig im .NET-Laden zu „kaufen“:
[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null [reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null $colorDialog1 = New-Object System.Windows.Forms.ColorDialog $colorDialog1.ShowDialog() $colorDialog1.color
Auch das folgende Script sollte noch ein paar Anregungen geben:
function GenerateForm {
# Assemblys laden [reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null [reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
# Objekte für Formen generieren $form1 = New-Object System.Windows.Forms.Form $label1 = New-Object System.Windows.Forms.Label $Open = New-Object System.Windows.Forms.Button $Cancle = New-Object System.Windows.Forms.Button $OK = New-Object System.Windows.Forms.Button $progressBar1 = New-Object System.Windows.Forms.ProgressBar $GruppeA = New-Object System.Windows.Forms.GroupBox $radioButton3 = New-Object System.Windows.Forms.RadioButton $radioButton2 = New-Object System.Windows.Forms.RadioButton $radioButton1 = New-Object System.Windows.Forms.RadioButton $GruppB = New-Object System.Windows.Forms.GroupBox $checkBox3 = New-Object System.Windows.Forms.CheckBox $checkBox2 = New-Object System.Windows.Forms.CheckBox $checkBox1 = New-Object System.Windows.Forms.CheckBox $openFileDialog1 = New-Object System.Windows.Forms.OpenFileDialog # Wenn Sie speichern Knöpfe haben möchten: $saveFileDialog1 = New-Object System.Windows.Forms.SaveFileDialog $InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
$checkbox=0,0,0 # Vorgabe in Form eines Arrays für die Checkboxen $radiobutton=1 # Vorgabe in Form einer Variablen für die Radiobuttons
# Ereigniscode für die einzelnen Knöpfe in Variablen hinterlegt $Cancle_OnClick= { # Wir wollen gar nicht wissen was mit dem Fenster passiert ist. Nur weg hier... ;-) $form1.close() }
$OK_OnClick= { # Bei Klick auf OK werden zum Schluß ein paar Status-Infos zurück gegeben $form1.close() write-host "Radiobutton: "$Radiobutton write-host "Checkboxstatus: "$checkbox -nonewline write-host write-host $label1.Text write-host "Fortschritt: "$progressBar1.Value }
$Open_OnClick= { # Hier wird der Datei öffnen Dialog erstellt. Ein openFileDialog1 | gm verrät mehr. $openFileDialog1.ShowHelp = $True $openFileDialog1.Title = "Datei öffnen" $openFileDialog1.InitialDirectory = "c:" $openfileDialog1.ShowDialog() $label1.Text=$openFileDialog1.FileName # In den nachfolgenden 5 Zeilen wird der Forschrittsbalken bei jeder Aktion etwas weitergerückt bis er voll ist und dann auf 0 zurück gesetzt if ($progressBar1.Value -lt 100) { $progressBar1.Value += 10 } else { $progressBar1.Value = 0 } }
$OnLoadForm_StateCorrection= {# Damit das Fenster nicht versehentlich maximiert startet. $form1.WindowState = $InitialFormWindowState }
$form1.BackgroundImageLayout = 3 # Hintergrundbild gekachelt, gestreckt, oder wie hätten wir's denn gerne? $form1.Font = New-Object System.Drawing.Font("Mistral",8.25,0,3,0) # Schriftart festlegen $form1.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon('C:\Pfad\IconDatei.ico') # Bild für das Icon festlegen $form1.Text = "Überschrift" $form1.Name = "form1" $form1.BackgroundImage = [System.Drawing.Image]::FromFile('C:\Pfad\Hintergrundbild.jpg') # Hintergrundbild einsetzen $form1.DataBindings.DefaultDataSourceUpdateMode = 0 $form1.ForeColor = [System.Drawing.Color]::FromArgb(255,0,0,255) # Schriftfarbe festlegen $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 332 $System_Drawing_Size.Height = 264 $form1.ClientSize = $System_Drawing_Size $form1.Opacity = 0.8 # Legt die Durchsichtigkeit fest 1=100% 0.1=10%
$label1.TabIndex = 6 # Tabindex legt die Tabulatorsprungreihenfolge fest $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 100 $System_Drawing_Size.Height = 23 $label1.Size = $System_Drawing_Size $label1.Text = "Keine Datei ausgewählt"
$System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 24 $System_Drawing_Point.Y = 184 $label1.Location = $System_Drawing_Point $label1.DataBindings.DefaultDataSourceUpdateMode = 0 $label1.Name = "label1"
$form1.Controls.Add($label1)
$Open.TabIndex = 5 $Open.Name = "Open" $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 91 $System_Drawing_Size.Height = 22 $Open.Size = $System_Drawing_Size $Open.UseVisualStyleBackColor = $True
$Open.Text = "Open"
$System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 24 $System_Drawing_Point.Y = 229 $Open.Location = $System_Drawing_Point $Open.DataBindings.DefaultDataSourceUpdateMode = 0 $Open.add_Click($Open_OnClick)
$form1.Controls.Add($Open)
$Cancle.TabIndex = 4 $Cancle.Name = "Cancle" $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 75 $System_Drawing_Size.Height = 23 $Cancle.Size = $System_Drawing_Size $Cancle.UseVisualStyleBackColor = $True $Cancle.Text = "Cancle" $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 243 $System_Drawing_Point.Y = 229 $Cancle.Location = $System_Drawing_Point $Cancle.DataBindings.DefaultDataSourceUpdateMode = 0 $Cancle.add_Click($Cancle_OnClick) $form1.Controls.Add($Cancle)
$OK.TabIndex = 3 $OK.Name = "OK" $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 75 $System_Drawing_Size.Height = 23 $OK.Size = $System_Drawing_Size $OK.UseVisualStyleBackColor = $True $OK.Text = "OK" $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 150 $System_Drawing_Point.Y = 229 $OK.Location = $System_Drawing_Point $OK.DataBindings.DefaultDataSourceUpdateMode = 0 $OK.add_Click($OK_OnClick) $form1.Controls.Add($OK)
# Eine Fortschrittsanzeige, die sich verändert je öfter man den Dateiöffnen Dialog aufruft $progressBar1.DataBindings.DefaultDataSourceUpdateMode = 0 $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 100 $System_Drawing_Size.Height = 23 $progressBar1.Size = $System_Drawing_Size $progressBar1.TabIndex = 2 $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 24 $System_Drawing_Point.Y = 153 $progressBar1.Location = $System_Drawing_Point $progressBar1.Name = "progressBar1" $progressBar1.Value = 0 # Die Skala geht von 0-100, die Änderung am Wert wird durch das Click-Ereignis beim Dateiöffnendialog vorgenommen $form1.Controls.Add($progressBar1)
# Durch Einbau der Gruppierung, weiß .NET automatisch, dass innerhalb einer Gruppe immer nur 1 Radiobutton geklickt sein darf im Gegensatz zu den Checkboxen.
$GruppeA.Name = "GruppeA" # Benamung des linke Gruppenfelds $GruppeA.Text = "Gruppe1" # Überschrift für das linke Gruppenfeld $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 119 $System_Drawing_Size.Height = 135 $GruppeA.Size = $System_Drawing_Size $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 12 $System_Drawing_Point.Y = 12 $GruppeA.Location = $System_Drawing_Point $GruppeA.BackColor = [System.Drawing.Color]::FromArgb(255,153,180,209) # Hintergrundfarbe festlegen $GruppeA.TabStop = $False $GruppeA.TabIndex = 0 $GruppeA.DataBindings.DefaultDataSourceUpdateMode = 0
$form1.Controls.Add($GruppeA) $radioButton3.TabIndex = 2 $radioButton3.Name = "radioButton3" $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 148 $System_Drawing_Size.Height = 31 $radioButton3.Size = $System_Drawing_Size $radioButton3.UseVisualStyleBackColor = $True $radioButton3.Text = "radioButton3" $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 16 $System_Drawing_Point.Y = 86 $radioButton3.Location = $System_Drawing_Point $radioButton3.DataBindings.DefaultDataSourceUpdateMode = 0 $radioButton3.TabStop = $True $radioButton3.add_Click({$radiobutton=3}) $GruppeA.Controls.Add($radioButton3)
$radioButton2.TabIndex = 1 $radioButton2.Name = "radioButton2" $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 149 $System_Drawing_Size.Height = 27 $radioButton2.Size = $System_Drawing_Size $radioButton2.UseVisualStyleBackColor = $True $radioButton2.Text = "radioButton2" $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 16 $System_Drawing_Point.Y = 53 $radioButton2.Location = $System_Drawing_Point $radioButton2.DataBindings.DefaultDataSourceUpdateMode = 0 $radioButton2.TabStop = $True $radioButton2.add_Click({$radiobutton=2}) $GruppeA.Controls.Add($radioButton2)
$radioButton1.TabIndex = 0 $radioButton1.Name = "radioButton1" $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 148 $System_Drawing_Size.Height = 27 $radioButton1.Size = $System_Drawing_Size $radioButton1.UseVisualStyleBackColor = $True $radioButton1.Text = "radioButton1" $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 17 $System_Drawing_Point.Y = 20 $radioButton1.Location = $System_Drawing_Point $radioButton1.DataBindings.DefaultDataSourceUpdateMode = 0 $radioButton1.TabStop = $True $radioButton1.add_Click({$radiobutton=1}) $GruppeA.Controls.Add($radioButton1)
# Bei den Checkboxen hätte man auch auf die Gruppierung verzichten können. Ist so aber übersichtlicher - finde ich.
$GruppB.Name = "GruppB" # Benamung des rechten Gruppenfelds $GruppB.Text = "Gruppe2" # Überschrift für das rechte Gruppenfeld $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 168 $System_Drawing_Size.Height = 195 $GruppB.Size = $System_Drawing_Size $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 150 $System_Drawing_Point.Y = 12 $GruppB.Location = $System_Drawing_Point $GruppB.BackColor = [System.Drawing.Color]::FromArgb(255,100,149,237) $GruppB.TabStop = $False $GruppB.TabIndex = 1 $GruppB.DataBindings.DefaultDataSourceUpdateMode = 0 $form1.Controls.Add($GruppB)
$checkBox3.UseVisualStyleBackColor = $True $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 104 $System_Drawing_Size.Height = 24 $checkBox3.Size = $System_Drawing_Size $checkBox3.TabIndex = 2 $checkBox3.Text = "checkBox3" $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 14 $System_Drawing_Point.Y = 112 $checkBox3.Location = $System_Drawing_Point $checkBox3.DataBindings.DefaultDataSourceUpdateMode = 0 $checkBox3.Name = "checkBox3" $checkBox3.add_Click({$checkbox[2]=1}) $GruppB.Controls.Add($checkBox3)
$checkBox2.UseVisualStyleBackColor = $True $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 104 $System_Drawing_Size.Height = 24 $checkBox2.Size = $System_Drawing_Size $checkBox2.TabIndex = 1 $checkBox2.Text = "checkBox2" $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 15 $System_Drawing_Point.Y = 66 $checkBox2.Location = $System_Drawing_Point $checkBox2.DataBindings.DefaultDataSourceUpdateMode = 0 $checkBox2.Name = "checkBox2" $checkBox2.add_Click({$checkbox[1]=1}) $GruppB.Controls.Add($checkBox2)
$checkBox1.UseVisualStyleBackColor = $True $System_Drawing_Size = New-Object System.Drawing.Size $System_Drawing_Size.Width = 104 $System_Drawing_Size.Height = 24 $checkBox1.Size = $System_Drawing_Size $checkBox1.TabIndex = 0 $checkBox1.Text = "checkBox1" $System_Drawing_Point = New-Object System.Drawing.Point $System_Drawing_Point.X = 15 $System_Drawing_Point.Y = 23 $checkBox1.Location = $System_Drawing_Point $checkBox1.DataBindings.DefaultDataSourceUpdateMode = 0 $checkBox1.Name = "checkBox1" $checkBox1.add_Click({$checkbox[0]=1}) $GruppB.Controls.Add($checkBox1)
# Status des Fensters sichern $InitialFormWindowState = $form1.WindowState # Die Funktion bei Aufruf des aufrufen $form1.add_Load($OnLoadForm_StateCorrection) # Fenster anzeigen $form1.ShowDialog()| Out-Null }
# Aufruf des Fenster, denn es wurde ja in eine Funktion eingebaut
GenerateForm
So, nun haben Sie genug Basiswissen. Noch ein kleiner Tipp: Suchen Sie mal im Internet nach „Primal Forms Community Edition„. Primal Script selbst kostet Geld, aber die Community Edition finden Sie an einigen Ecken des Internet zum kostenlosen Download. Da ich nicht sicher bin, ob man dies einfach so verbreiten darf, habe ich den direkten Link hier leider weg lassen müssen. Damit haben Sie einen grafischen Editor, der Ihnen den Powershellcode für komplexe GUI-Elemente zusammen baut. Sie brauchen Ihn nur noch nach Ihren Wünschen anzupassen.
Wie versprochen für die ganz Eiligen ein Modul mit einfachen Powershellbefehlen um ein Fenster mit Knöpfen, Texten, Inputboxen und sogar einem Kalender zu erstellen. Folgende Befehle werden derzeit unterstützt:
new-guiwindow (legt das Hauptfenster an)
new-guibutton (erstellt einen Knopf)
new-guitextbox (erstellt einen Textabschnitt)
new-guiinputbox (erstellt ein Eingabefeld)
new-guicalendar (erstellt eine Kalenderauswahl für Datumsangaben)
new-guidropdown (erstellt eine DropDownbox)
close-guiwindow (kann interaktiv ein Fenster schliessen)
set-guitextbox (kann interaktiv den Inhalt eine Textbox anpassen)
get-guiinputbox (kann interaktiv den Inhalt aus einer Inputbox abrufen)
show-guiwindow (zeigt das zusammengebaute Fenster an und liefert Rückgabewerte in Form eines Hashs)
Sollte das Zip-File mit den Scripten und Installationshinweisen nicht zum Download angezeigt werden, klicken Sie bitte auf die Artikelüberschrift.
Wenn Sie weitere interessante Praxistipps zu PowerShell lesen möchten oder PowerShell von Grund auf lernen möchten, werfen Sie doch einmal einen Blick in mein kostenloses Buch über PowerShell Programmierung. Auch das Kapitel über GUI-Programmierung mit PowerShell geht weit (z.B. Baumansichten – treeview, allerdings noch nicht veröffentlicht – nur für Spender ist die neueste Version zum download verfügbar) über das hier hinaus.
Einfache Powershell-Befehle für den Active Directory Papierkorb und eine GUI
Hier ein kleines Powershellscript, dass die Powershell um einfache Befehle für die Verwaltung und Einrichtung des Active Directory Papierkorbs erweitert (sollte der Downloadlink nicht angezeigt werden, klicken Sie bitte auf die Überschrift des Artikels):
Um den AD-Papierkorb zu aktivieren muss das Script als Organisationsadministrator ausgeführt werden, da nur dieser berechtigt ist im gesamten Forest den Papierkorb zu aktivieren. Dieses Feature kann nicht auf Domänenebene aktiviert werden. Der Forestlevel muss auf 2008 R2 hochgestuft sein. Falls Sie befürchten, dass irgendwelche schädlichen Aktionen im Script versteckt sind, schauen Sie einfach hinein, oder lassen Sie es von jemand überprüfen der sich damit auskennt.
Wurde der Papierkorb bereits aktiviert, kann das Script zukünftig auch als Domänenadministrator aufgerufen werden.
Das Script selbst schafft zunächst nur die Voraussetzungen für die Befehle, damit diese auf der aktuellen Maschine in der aktuellen Domäne ausgeführt werden können und baut die Befehle als Funktion in Ihre aktuell laufende Powershell ein. Wenn Sie die aktuelle Powershell Konsole schließen sind die Befehle auch schon wieder vergessen. Sie müssen also jedes mal das Script starten, bevor Sie auf die Befehle zugreifen können. Selbstverständlich dürfen Sie das Script auch verändern, damit es zukünftig zu Ihrem Standardbefehlssatz gehört.
Der Papierkorb kann nur Objekte wiederherstellen, die nach seiner Aktivierung gelöscht wurden. Die Befehle können alle Objekte wieder herstellen, also nicht nur Benutzer ,Gruppen OUs und Computer.
Hier nun die 3 einfachen Befehle zur Verwaltung des Papierkorbs die sich automatisch an die Domäne in der Sie sich angemeldet haben anpassen:
Start-RecycleBin
Achtung! Ist der Papierkorb aktiviert, kann diese Funktionalität (generell – auch über die Standardwerkzeuge) nicht mehr zurückgezogen werden.
Einfach nur eintippen und der Papierkorb wird aktiviert. Ggf. fragt das Script noch ein paar Dinge ab. Auf jeden Fall informiert der Befehl darüber ob der Papierkorb aktiviert ist.
Show-DeletedADObjects
Aufruf auch hier ohne weitere Parameter. Zeigt alle sich derzeit im Papierkorb befindlichen Objekte an.
Restore-DeletedADObjects Suchbegriff
Dieser Befehl holt gelöschte Objekte aus dem Papierkorb zurück. Geben Sie den Befehl gefolgt von einem Suchbegriff ein. Der Suchbegriff verarbeitet keine Platzhalterzeichen wie z.B. ein *. Dies wird automatisch im Script vor und nach dem Suchbegriff eingesetzt. Sollten Sie nicht wissen was Sie gelöscht haben, können Sie sich mit Show-DeletedADObjects einen Überblick über den Inhalt des Papierkorbs verschaffen.
Wenn Sie eine komplette OU gelyncht haben, können Sie einfach den Namen der OU angeben. Alle enthaltenen Objekte werden automatisch mit angezeigt.
Der Befehl stellt nicht einfach alles wieder her was dem Suchbegriff entspricht, sondern listet erst einmal alles was er zum Suchbegriff findet und fragt dann nach ob er die Objekte wiederherstellen soll. Dies beantworten Sie dann mit Ja oder Nein.
Grafische Oberfläche für den AD-Papierkorb mittels Powershellscript:
Wenn Sie zu den Mausschubsern gehören, können Sie auch das folgende Powershellscript nutzen um per GUI (grafischer Oberfläche) den AD-Papierkorb zu verwalten:
Vorteile des Scripts:
- Multiple Domain tauglich
- Löschzeitraum kann angegeben werden
- Schneller als so manche kommerzielle .EXE Datei
- Kann mit etwas Glück sogar Objekte restaurieren, die vor Aktivierung des Papierkorbs gelöscht wurden.
Das ZIP-Archiv ist in einen Ordner Ihrer Wahl zu entpacken. Darin enthalten sind ein paar Icons und das Script selbst. Einfach nur das Script ohne Parameter starten.
Der Einsatz der Scripte für den AD Papierkorb ist auch für den gewerblichen Einsatz kostenfrei. Gegen eine Spende (siehe PowerShell-Buch) habe ich aber sicher nichts einzuwenden ;-). Eine Haftung bei evtl. auftretenden Schäden wird nicht übernommen. Verbesserungsvorschläge nehme ich gerne über Kommentare oder das Kontaktformular entgegen.
Tesla Model S und X per PowerShell fernsteuern, mithilfe der Restful WebAPI von TESLA
Ich liebe meinen Tesla Model S und ich liebe PowerShell. Na dann bringe ich doch mal beides zusammen. 😀
Für die Anmeldung beim Tesla Restful Webservice müssen Sie dieselben Anmeldeinformationen (Benutzername und Kennwort), wie auf mytesla (https://my.teslamotors.com/de_DE/user/login) angeben. Also zunächst mal zur Authentifizierung:
# Fenster für Anmeldeinfos anzeigen
$Credential=Get-Credential
# Kennwort für die SSL-gesicherte Übergabe „vorbereiten“
$ptr=[Runtime.InteropServices.Marshal]::SecureStringToBSTR($Credential.Password)
$pwd=[Runtime.InteropServices.Marshal]::PtrToStringAuto($Ptr)
# Notwendige Anmeldeinformationen zusammensetzen
$LoginInfo=@{
‚grant_type‘ = ‚password‘
‚client_id‘ = „e4a9949fcfa04068f59abb5a658f2bac0a3428e4652315490b659d5ab3f35a9e“
‚client_secret‘ = „c75f14bbadc8bee3a7594412c31416f8300256d7668ea7e6e7f06727bfb9d220“
‚email‘ = $Credential.UserName
‚password‘ = $pwd
}
Dann können Sie die Verbindung unter Angabe der Anmeldeinfos herstellen:
$Connect = Invoke-RestMethod -Uri „https://owner-api.teslamotors.com/oauth/token“ -Method Post -Body $LoginInfo
Als Rückgabewert erhalten Sie dann einen Zugriffsschlüssel (Token) mit dem alle weiteren Aktionen durchgeführt werden können:
$Token=$Connect.access_token
Hier noch ein paar allgemeine, notwendige http Header Informationen zusammen schrauben:
$Header=@{
„Authorization“=“Bearer $Token“
„Accept-Encoding“=“gzip,deflate“
}
Gehen wir mal davon aus, Sie haben nur einen Tesla, dann finden Sie mit dem nachfolgenden Kommando in $car allgemeine Informationen zu Ihrem Fahrzeug wie Farbe, Name u.v.a.m.
$car = (Invoke-RestMethod -Uri „https://owner-api.teslamotors.com/api/1/vehicles“ -Method Get -Headers $Header).response
Falls Ihr Dornröschen noch schläft, müssen Sie es erst mal wach küssen:
if ($car.state -ne „online“) {Invoke-RestMethod -Uri „https://owner-api.teslamotors.com/api/1/vehicles/$($car.id)/wake_up“ -Method Post -Headers $Header}
Jetzt können Sie Ihren Liebling mal etwas genauer untersuchen, wie z.B. die eingestellten Einheiten (gui_settings) abfragen:
(Invoke-RestMethod -Uri „https://owner-api.teslamotors.com/api/1/vehicles/$($car.id)/data_request/gui_settings“ -Method Get -Headers $Header).response
Den Teil gui_settings können Sie gegen die folgenden Begriffe austauschen:
charge_state = Zeigt den Akkustatus an
climate_state = Klima Anlage
drive_state = GPS Infos
vehicle_state = Zustandsinformationen: km-Stand, Schiebedach auf? etc…
Sie dürfen natürlich auch gerne Einstellungen vornehmen (z.B. hupen):
Invoke-RestMethod -Uri „https://owner-api.teslamotors.com/api/1/vehicles/$($car.id)/command/honk_horn“ -Method Post -Headers $Header
Auch hier gibt’s wieder einen ganzen Sack voll weiterer Begriffe, die Sie gegen honk_horn austauschen können:
flash_lights = Lichthupe
charge_port_door_open = Ladeanschluß öffnen
charge_standard = Ladelimit auf Standard setzen
charge_max_range = Ladelimit auf max. Reichweite (100%) setzen
set_charge_limit?percent=75 = Ladelimit beliebig einstellen
charge_start und charge_stop = Ladevorgang starten bzw. beenden
door_lock und door_unlock = Türen auf bzw. zu
set_temps?driver_temp=23.7&passenger_temp=18.1 = wie warm soll’s darf’s denn sein?
auto_conditioning_start und auto_conditioning_stop = Klima an bzw. aus
sun_roof_control?state=open&percent=50 = Schiebedach steuern
remote_start_drive?password=StrengGeheim = Kennwort für den Start ohne Schlüssel im Fahrzeug festlegen. Verfällt nach 2 Minuten, wenn das Fahrzeug nicht bis dahin gestartet wird.
PowerShell Script um Quest-Migration-Manager Datenbank aufzuräumen
Das folgende Script löscht Einträge aus der Ressource Processing Datenbank des Quest Migration Manager, die älter als 3 Monate sind:
# Bitte unter dem Namen cleanQuestDB.ps1 abspeichern, damit das u.a. Beispiel passt
param(
[String]$Server=“localhost“,
[int]$Port=50000,
[int]$Month=3,
[String]$LogPath=“~\Desktop\DeletedQuestDBEntries.log“
)
Import-Module ActiveDirectory
$ErrorActionPreference=“SilentlyContinue“
Get-ADObject -filter * -server „$($Server):$($Port)“ -searchbase *
$Root=($Error[0] | select -expandprop Exception | select -expandprop message).split(„:“)[1].split(„,“)[-1].substring(1).trimend(„‚.“)
$ErrorActionPreference=“Continue“
$Project=(Get-ADObject -filter * -server „$($Server):$($Port)“ -searchbase $Root -searchscope Onelevel | ? {$_.ObjectClass -eq „aelita-Amm-Workspace“}).Distinguishedname
$ComputerLogCollection=Get-ADObject -filter * -server „$($Server):$($Port)“ -searchbase „cn=Computers,cn=ResourceProcessing,$Project“ -searchscope onelevel -properties aelita-Amm-LastOperationTime,aelita-Amm-Name
$TimeSpan=(get-date)-(new-timespan -days ($Month*30))
$ToDelete=@()
$TotalCounter=$ComputerLogCollection.count
$DeleteCounter=0
„Searching Database. Please be patient!“
foreach ($Item in $ComputerLogCollection) {
$Timestamp=$Item | select -expandprop aelita-Amm-LastOperationTime
if ($Timestamp -and $Timestamp -lt $TimeSpan) {
$ToDelete+=$Item
$DeleteCounter++
}
}
if ((read-host -prompt „$DeleteCounter from $TotalCounter to delete, proceed (Yes/No)“) -notlike „Y*“) {„Aborted!“;exit}
„Deleted Entries of Questdatabase“ > $LogPath
„Run from: $(get-date)“ >> $LogPath
foreach ($Item in $ToDelete) {
$Name=$Item | select -expandprop aelita-Amm-Name
$Timestamp=$Item | select -expandprop aelita-Amm-LastOperationTime
„Deleting $Name from $Timestamp“ | tee $LogPath -Append
$Item | Remove-ADObject -Recursive -confirm:$false
}
Im einfachsten Fall starten Sie einfach das Script. Zunächst wird geschaut wieviele Einträge insgesamt vorhanden sind und wieviele davon gelöscht werden würden. Dann fragt es, ob Sie den Vorgang durchführen möchten und listet Ihnen die entsprechenden Objekte auf. Nebenbei werden diese Angaben in eine LogDatei auf Ihrem Desktop protokolliert. Sie können das Skript natürlich auch mit anderen Parametern aus dem Parameter Block aufrufen, wie z.B.:
./cleanQuestDB.ps1 -Server QuestServer -Port 40000 -Month 2 -LogPath C:\Quest.log
Voraussetzungen:
PowerShell 2.0 oder höher
AD-Modul verfügbar
Der Benutzer unter dem das Script läuft benötigt Vollzugriff auf die Quest-Datenbank
Muss mit erhöhten Rechten (UAC – Benutzerkontensteuerung) ausgeführt werden
Powershellscripte zur Verwaltung von Hyper-V
Wenn Sie kein SCVMM (System Center Virtual Machine Manager) Ihr eigen nennen wäre es doch trotzdem ganz nett einige Dinge davon selbst über Powershell zu machen. Microsoft hat eine Powershell Script Sammlung zur Hyper-V Verwaltung bereit gestellt. Damit können Sie u. a. virtuelle Maschinen und Snapshots bzw. Checkpoints erstellen und verwalten aber auch vhd’s konvertieren und noch vieles mehr. Die Sammlung wir stetig erweitert. Mit der Anleitung Powershell GUI-Programmierung für Dummies auf dieser Seite könnten Sie sich Ihren eigenen SCVMM zusammen bauen. Wenn ich einmal viel Langeweile habe mache ich das vielleicht für Sie ;-).
Von der Eingabeaufforderung Parameter an Powershellscripte übergeben
Was passiert, wenn Sie ein Powershellscript doppelklicken? Das ist natürlich davon abhängig, welche Zusatzsoftware (z.B. PowerGui) Sie installiert haben, doch standardmäßig wird unter Windows Server 2008 R2 z. B. der Texteditor Notepad gestartet anstatt das Script auszuführen. Das ist auch noch so eine tolle Schutzmaßnahme, die das Ausführen von „bösen“ (und natürlich auch guten) Powershellscripten erschweren soll. Das ist auch der Grund warum sich keine Parameter an Powershellscripte übergeben lassen. Dieser Registry-Hack beseitigt das Problem:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\open\command] @="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" \"-file\" \"%1\" %*"
Wenn Sie mögen können Sie den schräg dargestellten Text einfach in einer Datei mit der Endung .reg abspeichern und doppelklicken. Danach können Sie per Doppelklick die Powershell-Scripte starten und auch Parameter übergeben.
Innerhalb des Powershellscripts können Sie die Parameter entweder über die Variable $args oder $Input abfragen. Bei mehreren Parametern mit $args[0] den 1., $args[1] den 2. etc…
Windows Server 2008 Core mit GUI
Windows Server 2008 Core als auch die R2 Version enthalten offensichtlich doch grafische Gestaltungselemente. Als Beweis tippen Sie doch einmal notepad, regedit oder timedate.cpl ein und drücken Enter/Return. Wie sagt man doch immer so schön: Der Laie staunt, der Fachmann wundert sich ;-).
Nun, also wenn Grafik geht, warum dann mühevoll auf der Kommandozeile z.B. die IP- und Firewallkonfiguration vornehmen?
Für Windows Server 2008 gibt es den Core Configurator 1.1 und für den R2 den Core Configurator 2.0. Kostenlos runterladen, auf CD brennen und Sie können von nun an alles grafisch einstellen.
Falls Sie Bedenken wegen der Sicherheit haben…es liegt jeweils im Quellcode vor, bzw. der Core Configurator 2.0 besteht „nur“ aus einer Sammlung von Powershellscripten, die Sie auch selbst schreiben könnten und in der Version 1.1 sind es vbs-Dateien also VisualBasicScript.
Da es auf Server 2008 keine Powershellunterstützung gibt ist Core Configurator 1.1 als ausführbares Programm auf der CD. Damit Sie die Powershellscripte vom Core Configurator 2.0 benutzen können, müssen Sie auch beim R2 erst die Powershell und das .NET Framework (gibt’s auch nicht auf dem 2008 – ohne R2) als Feature nachrüsten. Das geht wie folgt:
Installieren Sie mit ocsetup „NetFx2-ServerCore“ erst das .NET-Framework und danach mit ocsetup „MicrosoftWindowsPowerShell“ die Powershell. Ausnahmsweise bitte einmal die Groß-/Kleinschreibung beachten!
Nun können Sie mit dem Befehl start c:\windows\system32\powershell\v1.0\powershell eine Powershell Kommandozeile starten. Ohne „start“ würde die aktuelle Kommandozeile zur Powershell.
Auf der Powershell müssen Sie zunächst den Befehl set-executionpolicy unrestricted eingeben, damit die Scriptausführung zugelassen wird. Wenn Sie Ahnung haben, können Sie natürlich auch eine andere executionpolicy wählen. Allerdings kann man die sowieso jederzeit umstellen – sogar ohne Admin zu sein! So nun können Sie die Powershellscripte von der CD aufrufen um all Ihre Einstellungen (Computername, Aktivierung, IP- u. Firewallkonfiguration, Benutzerverwaltung, etc…) grafisch vorzunehmen.
XML-Abfrage Ereignisanzeige
Die Filter für die Windows Ereignisanzeige (Eventlog) sind sehr mächtig geworden. Mit den standard Optionen in der grafischen Oberfläche kann man schon viel machen, aber leider nicht im Nachrichtentext filtern. Das geht auch mit XML Abfragen. Klicken Sie dazu zunächst einmal auf ein ähnliches Ereignis und klicken Sie dort die Detailansicht an. Dort wählen Sie XML View:
Dann erstellen Sie einen benutzerdefinierten Filter und wählen dort den Reiter XML. Setzen Sie das Häkchen bei Abfrage manuell bearbeiten. Wenn Sie bereits bei Filter Reiter Einstellungen gemacht haben, sind diese auch schon im XML hier vordefiniert. Haben Sie z.B. das Anwendungslog ausgewählt steht dort:
<QueryList>
<Query Id=“0″ Path=“Application“>
<Select Path=“Application“>*</Select>
</Query>
</QueryList>
Oben habe ich Sie den XML-View auswählen lassen. Warum? Dort sehen Sie, wie die jeweiligen Felder nach denen Sie suchen können benannt sind. Um nun also z.B. nach dem Benutzernamen zu suchen ergänzen Sie die XML Zeilen wie folgt:
<QueryList>
Id=“0″ Path=“Security“>
<Select Path=“Security“>*</Select>
*[EventData[Data[@Name=‘TargetUserName‚] and (Data=‘s‚)]]
</Select>
</Query>
</QueryList>
Selbstverständlich dürfen Sie das gerne weiter verkomplizieren:
*[EventData[Data[@Name=’SubjectUserName‘] and (Data=’abc‘ or Data=’123’)]]
Dies würde alle mit der Angabe abc oder 123 finden bei UserName finden.
Möchten Sie in mehreren Logs suchen:
<Select Path=“Security“>*[System[(EventID=’1234′)]]</Select>
<Select Path=“Application“>*[System[(EventID=’4321′)]]</Select>
Würde alle Ereignisse aus dem Eventlog Security mit der ID 1234 und alle Ereignisse aus dem Applicationlog mit der ID 4321 anzeigen.
Um die Filter in der PowerShell zu nutzen können Sie die XML-Abfrage genauso in einen String schreiben und mit Get-WinEvent abfragen:
$Query=@“
<QueryList>
Id=“0″ Path=“Security“>
<Select Path=“Security“>
*[EventData[Data[@Name=’TargetUserName‘] and (Data=’s‘)]]
</Select>
</Query>
</QueryList>
„@
$Evts=Get-WinEvent -log Security -FilterXPath $Query -maxevents 1000
Profil
Profil
Persönliche Daten
Name: Martin Lehmann
Geburtsjahr: 23.11.1969
Tel.: 0177/3335259
e-Mail: webmaster@martinlehmann.de
Ausbildung/Werdegang
Ausbildung zum Chemikant
4 Jahre Flugsicherung/Flugdatenverarbeitung
Selbständiger IT Consultant und Trainer
Dipl. PC-Betreuer
Fremdsprachen
Englisch, Ungarisch
Tätigkeitsschwerpunkt
Active-Directory Konsolidierung und Migration. PowerShell-Automatisierung.
Dozent für Schulungen im heterogenen Umfeld (LINUX,MS,Novell). Projektmanagement.
Einsatzdaten
Verfügbar ab: Dez. 2019
Kapazität: Fulltime
Programmiersprachen
Lange her: Basic, Assembler, Pascal, HTML, JAVA, VBS, Perl
Aktuell: PowerShell und .NET
Datenbanken
Access, MS-SQL, MY-SQL: nicht mein Schwerpunkt.
Betriebssysteme
Nach Kenntnisgrad gestaffelt:
Alle von Microsoft seit DOS, Linux/Unix, Novell, OS/2
Hardware
PCs
Produkte/Standards/Erfahrungen
ACA (Astaro certified Administrator + Trainer), MCP+I, MCSA, MCSE, MCT, MCTS, MCITP Enterprise Administrator (MOC: Basis, Design, IIS, Hyper-V, Cluster und Windows – alle Versionen), PowerShell, .NET, LPIC-Level 1+2, CNI, CLP, Dell Migration Manager, ITIL Grundlagen, Projektmanagement, BSI, ISO 27001
Publikationen
Open-Book: Powershell 1-2-3
Link: http://www.martinlehmann.de/PowerShell123.htm
Projekterfahrung
04/19-dato
Branche: Healthcare, GKVI
Tätigkeit: 3rd Level Support Active-Directory.
Umgebung: PowerShell, Active-Directory, Exchange, Fileserver, Azure, One IDM, LDS
04/18-03/19
Branche: Anlagenbau/Automotive, Voith/Leadec
Tätigkeit: Entwicklung eines Workflow Management Tools in PowerShell.
Umgebung: PowerShell, Active-Directory, MS-SQL, IIS, Exchange, Fileserver
02/17-04/18
Branche: Anlagenbau/Automotive, Leadec/Voith//Veltec
Tätigkeit: Workstreamlead im globalen Carveout-Projekt. Projektmanagement und stellvertretend Programmanagement beim Herauslösen der Leadec und Veltec Firmengruppe aus dem Voith Konzern, sowie die Integration eines weiteren Unternehmens.
Standards: ITIL, Scrum
06/16-12/16
Branche: Healthcare, Apollo Optik Holding
Tätigkeit: AD-Restukturierung.
Produkte: Active-Directory, GPO, PowerShell, Direct-Access, Office 365
10/16
Branche: Versandhandel, Bruno Bader
Tätigkeit: AD-Restukturierungs Beratung.
Produkte: Active-Directory, GPO, PowerShell.
08/16
Branche: Fernwirktechnik, ids
Tätigkeit: Faulttolerance Cluster Disaster-Recovery Lösung mit PowerShell automatisiert.
Produkte: Everrun, PowerShell, Oracle, SCADA.
05/13-12/15
Branche: Healthcare, Fresenius (Net-Care)
Tätigkeit: Migration und Konsolidierung von mehr als 100 Active Directory Domänen weltweit. Von Linux\Samba über Windows 2000 bis Windows 2012 wurden diese in fünf 2008 R2 Domänen zusammengefasst. PowerShell Scripting bis hin zu technischer Projektleitung. Entwurf von DFS und CA-Konzepten.
Produkte: Quest, PowerShell, Active-Directory, MS-Office 2013, Lotus Notes
07/12-05/13
Branche: Internet-Portal, AutoScout24
Tätigkeit: Senior Webserveradministrator. Verwalten der Webplattform AutoScout24 und angekoppelter Systeme. Ausrollen, der täglichen Releases, Patching, Troubleshooting. Entwicklen von Adminwerkzeugen zur Vereinfachung und Automatisierung mittels PowerShell. Betriebssprache: Deutsch und Englisch.
Produkte: IIS 7.5, PowerShell, Active-Directory, RepliWeb, PRTG, VMWare Cloud, F5,
Gomez, Dynatrace, Splunk
09-12/10
Branche: Transport, Deutsche Bahn AG
Tätigkeit: Security Manager im Riskmanagement. Erstellen von Schutzbedarfsfeststellungen, Risikoanalysen und Restrisikodeklarationen in Deutsch und Englisch.
Produkte: Management, ISO 27001, BSI Grundschutz, ITIL
10-12/08
Branche: Transport, Deutsche Bahn AG
Tätigkeit: Security Manager im Riskmanagement. Erstellen von Schutzbedarfsfeststellungen, Risikoanalysen und Restrisikodeklarationen in Deutsch und Englisch.
Produkte: Management, ISO 27001, BSI Grundschutz, ITIL
01/07
Branche: Versandhandel, Reppa
Tätigkeit: Optimierung IIS 6.0 für Webshop.
Produkte: Windows Server 2003
02-03/05
Branche: Versicherung, Standard Life
Tätigkeit: Migration von 3 Windows NT Domänen auf eine Windows Server 2003 AD-Struktur.
Produkte: NT, W2k, XP, Windows Server 2003
12/04
Branche: öffentlicher Dienst, Verwaltungsfachhochschule Wiesbaden
Tätigkeit: Migration eines Windows 2000 Clusters auf Windows Server 2003.
Produkte: W2k, XP, 2003, ISA, Exchange, Clusterserver
12/04
Branche: Medien, Offenbach-Post
Tätigkeit: Migration Windows NT/2000 auf Windows Server 2003.
Produkte: NT4.0, W2k, XP, 2003, Apple Macintosh
02-04/03
Branche: öffentlicher Dienst, Hessische Zentrale f. Datenverarbeitung
Tätigkeit: Windows Server 2003 Implementation in heterogene Netzwerklandschaft.
Produkte: NT4.0, W2k, XP, 2003, Terminalservices
06/02
Branche: Religion, Haus am weißen Stein
Tätigkeit: Serversetup.
Produkte: LINUX-File- u. TK-Server (Ben Hur)
07-08/01
Branche: IT, Comlog
Tätigkeit: Netzwerkanalyse zur Optimierung des Netzwerkverkehrs.
Produkte: Netzwerk- u. Systemmonitor von Microsoft
01-06/01
Branche: Industrie, bei Infraserv
Tätigkeit: Ausbildung der Active Directory Designer und Administratoren. Unterstützung bei der AD-Planung und Einführung.
Produkte: Windows 2000, VISIO
03-09/00
Branche: Industrie, bei HiServ
Tätigkeit: Ausbildung der Active Directory Designer und Administratoren. Unterstützung bei der AD-Planung und Einführung.
Produkte: Windows 2000, VISIO
01-02/00
Branche: Industrie, bei Siemens
Tätigkeit: Ausbildung der ersten Active Directory Designer und Administratoren in Deutschland.
Produkte: Windows 2000, VISIO
04/99
Branche: Industrie, bei Lufthansa Cargo
Tätigkeit: Access-Datenbank-Programmierung.
Produkte: Access
12/98-01/99
Branche: Finanzen, bei FKB
Tätigkeit: Teilweise Netzwerkrestrukturierung und Domänenkonsolidierung, Umbau der Netzwerkinfrastruktur.
Produkte: Vernetzte Windows PCs (alle Versionen) im Ethernet-Netzwerk
01-04/98
Branche: Bank, bei ABN AMRO
Tätigkeit: Überarbeitung der bestehenden Domänenstruktur.
Produkte: Vernetzte Windows PCs (alle Versionen) im Ethernet-Netzwerk
11/97-06/98
Branche: Lebensmittel, Ferrero
Tätigkeit: Konzeption und Durchführung einer Restrukturierung der Netzwerkinfrastruktur. Domänenkonsolidierung.
Produkte: Vernetzte Windows PCs (alle Versionen) im Ethernet-Netzwerk
10/97
Branche: Spedition, bei SJG
Tätigkeit: Implementierung einer Antivirenlösung.
Produkte: Dr. Solomons AV-Toolkit
04-06/97
Branche: Bank, bei ABN AMRO Bank
Tätigkeit: Konzeption für Netzwerkrestrukturierung.
Produkte: Vernetzte Windows PCs (alle Versionen) im Ethernet- und Token-Ring-Netzwerk
03/97
Branche: Architektur, bei Lawrenz GmbH
Tätigkeit: Workstationrollout.
Produkte: Windows + AutoCAD, Setupmanager und Sysdiff
08/96
Branche: Transport, bei KVG
Tätigkeit: Implementation und Aufbau einer auf Windows-Domänen basierenden Infrastruktur.
Produkte: Microsoft Windows
06/96
Branche: Finanzen, bei ALO
Tätigkeit: DATEV Online Lösung realisiert.
Produkte: DATEV
05/96
Branche: Transport, bei KVG
Tätigkeit: Implementierung einer Antivirenlösung.
Produkte: Dr. Solomons AV-Toolkit
04/96
Branche: Bank, bei OFB
Tätigkeit: PC-Umzug
Produkte: Vernetzten von Windows (alle Versionen) PCs und Netware-Servern
02/96
Branche: Architektur, bei Grandjean
Tätigkeit: Implementierung 100VG Anylan.
Produkte: Switches von HP
Schulungen immer wieder zwischen und während den Projekten:
04-dato
Branche: Banken, Versicherungen, Industrie, Transport, öffentlicher Dienst, etc..
Tätigkeit: Microsoft und LINUX-Schulungen.
Produkte: NT 4.0, W2k, XP, 2003, 2003 R2, Vista, 2008, 7, 2008 R2, IIS, ISA, Hyper-V, Cluster, Sharepoint, SuSE, RedHat, Solaris
97-04
Branche: Banken, Versicherungen, Industrie, Transport, öffentlicher Dienst, etc..
Tätigkeit: MOC-Schulungen
Produkte: NT 4.0, W2k, XP, 2003
96
Branche: Banken, Versicherungen, Industrie, Transport, öffentlicher Dienst, etc..
Tätigkeit: Schulungen
Produkte: Windows, MS-Office
03-08
Branche: Fernschule (SGD)
Tätigkeit: Fernlehrer und Seminarleiter. Entwicklung Schulungsmaterial und Prüfungen
der Fernlehrgänge (u. a. Dipl. Netzwerkadministrator, Dipl. Netzwerkmanager)
im Bereich Betriebssysteme.
Produkte: NT 4.0, W2k, 2003, Linux
Numerische Auflistung der durchgeführten MOC-Schulungen:
(ohne Kurse aus der Coursewarelibrary – diese Liste wäre noch einmal so lang)
Course # Course Name
1561, 1664, 1665 Designing a Microsoft Windows 2000 Directory Services Infrastructure
1567 Preinstalling and Deploying Microsoft Windows 2000 Professional
2028 Basic Administration of Microsoft Windows 2000
2087, 2117 Implementing Microsoft Windows 2000 Clustering
2123 Jump Start: Upgrading from Microsoft Windows NT 4.0 to Windows Server 2003
2125-26, 2129-30 Managing a Microsoft Windows 2000 Network Environment
2150, 2079 Designing a Secure Microsoft Windows 2000 Network
2151,2045,2046,2266 Microsoft Windows 2000 Network and Operating System Essentials
2152-54, 2267 Implementing Microsoft Windows 2000 Professional and Server
2153 Implementing a Microsoft Windows 2000 Network Infrastructure
2154, 2175 Implementing and Administering Microsoft Windows 2000 Directory Services
2159, 2160-62 Deploying and Managing Microsoft Internet Security and Acceleration Server 2000
2199 Jumpstart: Active Directory Fundamentals
2207 Expert Track: Updating Systems Administrator and Systems Engineer Skills from Microsoft Windows 2000 to Windows Server 2003
2208,2218-19,2221-22 Updating Support Skills from Microsoft Windows NT 4.0 to Windows Server 2003
2209 Expert Track: Updating Systems Administrator Skills from Microsoft Windows 2000 to Windows Server 2003
2210 Expert Track: Updating Systems Engineer Skills from Microsoft Windows 2000 to Windows Server 2003
2215 Implementing and Managing Microsoft Windows Storage Server 2003
2272, 2615-2621 Implementing and Supporting Microsoft Windows XP Professional
2273 Managing and Maintaining a Microsoft® Windows Server™ 2003 Environment
2274, 2144-45,
2147, 2605 Managing a Microsoft® Windows Server™ 2003 Environment
2275, 2149, 2163,
2165, 2606 Maintaining a Microsoft Windows Server 2003 Environment
2276 Implementing a Microsoft Windows Server 2003 Network Infrastructure: Network Hosts
2277 Implementing, Managing, and Maintaining a Microsoft Windows Server 2003 Network Infrastructure: Network Services
2278, 2189-93 Planning and Maintaining a Microsoft Windows Server 2003 Network Infrastructure
2278 Planning and Maintaining a Microsoft® Windows Server® 2003 Network Infrastructure
2279, 2194-98 Planning, Implementing, and Maintaining a Microsoft Windows Server 2003 Active Directory Infrastructure
2279 Planning, Implementing, and Maintaining a Microsoft® Windows Server® 2003 Active Directory® Infrastructure
2282, 2096-98 Designing a Microsoft® Windows Server™ 2003 Network and Active Directory® Infrastructure
2283 Migrating from Microsoft Windows NT to Microsoft Windows Server 2003
2285, 2223-27 Installing, Configuring & Administering Microsoft® Windows® XP Professional
2285 Installing, Configuring, and Administering Microsoft® Windows® XP Professional Service Pack 2
2289 Deploying Business Desktops with Microsoft® Windows® XP and Microsoft® Office 2003
2295 Implementing and Supporting Microsoft Internet Information Services 5.0
2297, 2235-37 Planning, Implementing, Managing, and Maintaining a Microsoft Windows Server 2003 Environment for an MCSE on Windows 2000
2299 Managing and Maintaining a Microsoft Windows Server 2003 Environment for an MCSA on Windows 2000
2433 Microsoft Visual Basic Scripting Edition and Microsoft Windows Script Host Essentials
2439 Scripting Microsoft Windows Management Instrumentation
2505 Deploying Microsoft Office XP
2520 Deploying Microsoft Windows XP Professional
2576 Implementing and Administering Microsoft Internet Information Services (IIS) 6.0
2694 Updating Web Server Skills to Internet Information Services 6.0
2731 Deploying and Managing Microsoft® Identity Integration Server 2003
2801, 2750-53, 2758 Microsoft® Security Guidance Training I
2802, 2759-62, 2767 Microsoft Security Guidance Training II
2803, 2516,
2518-19, 2529 Microsoft Security Guidance Training III
2804, 2900-03, 2908 Microsoft Security Guidance Training IV
2808, 2670,
2672-74, 2923 Microsoft Security Guidance Training V
2810 Fundamentals of Network Security
2820, 2230-32 Implementing and Administering Security in a Microsoft® Windows® 2000 Network
2821 Designing and Managing a Windows Public Key Infrastructure
2823 Implementing and Administering Security in a Microsoft® Windows Server™ 2003 Network
2824 Implementing Microsoft Internet Security and Acceleration Server 2004
2830 Designing Security for Microsoft® Networks
2851, 2441-44 Deploying and Administering Windows® XP Service Pack 2
2855 Managing Security Enhancements in Windows Server 2003 Service Pack 1
4356 Managing Branch Office Resources Using Microsoft® Windows Server™ 2003 R2
4357 Managing Data Storage Using Microsoft® Windows Server™ 2003 R2
4360 Getting Started with Microsoft® Windows Server™ 2003 R2
5115 Installing, Configuring, and Troubleshooting Windows Vista®
5118 Supporting Windows Vista® and Applications in the Enterprise
5131, 5402,
5925-26, 5973 Designing, Deploying, and Managing a Network Solution for a Small and Medium-Sized Business
6044 Implementing Active Directory Identities and Access in Windows Server 2008 (Beta)
6047 Implementing Network Access Protection in Windows Server 2008 (Beta)
6289, 10170 First Look Clinic: Windows® 7 Beta for IT Professionals
6291 Updating Your Technology Knowledge of Microsoft® Windows® XP to Windows® 7 Beta
6292, 10224-26,
10228, 10561 Installing and Configuring Windows® 7 Client
6294, 10220, 10223 Planning and Managing Windows® 7 Desktop Deployments and Environments
6331 Deploying and Managing Microsoft® System Center Virtual Machine Manager
6400, 7086 First Look Clinic: Getting Started with Terminal Services in Windows Server® 2008
6402 First Look Clinic: Getting Started with Branch Office Management in Windows Server® 2008
6404 First Look Clinic: Getting Started with High Availability in Windows Server® 2008
6406, 7092 First Look Clinic: Getting Started with Security and Policy Control in Windows Server® 2008
6408 First Look Clinic: Getting Started with Server Management in Windows Server® 2008
6410 First Look Clinic: Getting Started with Windows Server® 2008 Hyper-V™
6412, 7098 First Look Clinic: Getting Started with Internet Information Services in Windows Server® 2008
6416 Updating your Network Infrastructure and Active Directory® Technology Skills to Windows Server® 2008
6417, 6195, 6731, 6735 Updating your Applications Infrastructure Technology Skills to Windows Server® 2008
6418 Deploying Windows Server® 2008
6419, 10136-38,
10140 Configuring, Managing and Maintaining Windows Server 2008 Servers
6420 Fundamentals of Windows Server® 2008
6421, 6741-43, 6822,
6829, 6852, 10221 Configuring and Troubleshooting a Windows Server® 2008 Network Infrastructure
6422 Implementing and Managing Windows Server® 2008 Hyper-V™
6423 Implementing and Managing Windows Server® 2008 Clustering
6425 Configuring and Troubleshooting Windows Server® 2008 Active Directory® Domain Services
6425, 6237-39,
10222 Configuring and Troubleshooting Windows Server® 2008 Active Directory® Domain Services
6425 Configuring Windows Server 2008 Active Directory Domain Services
6426, 10229-30 Configuring and Troubleshooting Identity and Access Solutions with Windows Server® 2008 Active Directory®
6426 Configuring and Troubleshooting Identity and Access Solutions with Windows Server® 2008 Active Directory®
6426 Configuring Identity and Access Solutions with Windows Server 2008 Active Directory
6427, 6744-46,
6826, 6833, 6854 Configuring and Troubleshooting Internet Information Services in Windows Server® 2008
6428, 6855 Configuring and Troubleshooting Windows Server® 2008 Terminal Services
6429, 6738-40 Configuring and Managing Windows Media® Services for Windows Server® 2008
6430, 10080 Planning for Windows Server® 2008 Servers
6431 Managing and Maintaining Windows Server® 2008 Network Infrastructure Servers
6432 Managing and Maintaining Windows Server® 2008 Active Directory® Servers
6434 Automating Windows Server® 2008 Administration with Windows PowerShell™
6435, 10036, 10184 Designing a Windows Server® 2008 Network Infrastructure
6436, 6873, 10185 Designing a Windows Server® 2008 Active Directory® Infrastructure and Services
6437 Designing a Windows Server 2008 Applications Infrastructure
6437 Designing a Windows Server® 2008 Applications Infrastructure
7245 Updating your Windows Server 2003 Server Administrator Skills to Windows Server 2008
7246 Planning Windows Server 2008 Server Roles
7247 Creating a Windows Server 2008 Server Deployment Plan
7248 Managing a Windows Server 2008 Server Infrastructure
7249 Monitoring and Maintaining Windows Server 2008 Servers
7250 Managing Applications in a Windows Server 2008 Environment
7251 Maintaining Windows Server 2008 Active Directory Domain Services
7252 Maintaining Security in a Windows Server 2008 Environment
7253 Planning for Windows Server 2008 High Availability and Recovery
Dauerbetreuung:
94-dato
Betreuung eines eigenen heterogenen Testnetzwerks:
Dauerhaft in Betrieb: 1 Windows Domänencontroller, 1 IIS, 1 Sophos UTM (ehem. Astaro), 1 Hardwarefirewall, 5 Windows Clients, 2 SuSE Linux Clients, WLAN
Zusätzlich in Betrieb: Für verschiede Testscenarien teilweise über VMWare und Virtual PC alle gängigen OS (u. a. verschiede UNIX- [z. B. Solaris] u. LINUX-Derivate [z.B. Cent OS – Red Hat, Ubuntu])
01-dato
IT Betreuung und Beratung von 4 kleineren (bis zu 20 Mitarbeiter) Betrieben:
1 Consultingunternehmen, 1 Steuerberater, 1 Künstleragentur, 1 Gemeinschaftspraxis