Windows PowerShell

An diversen Stelle der MSXFAQ werden Hinweise zu Powershell mit dem Icon gekennzeichnet.

WinRM und Powershell 2 gehören zusammen und sind bei Windows 7 und Windows 2008 R2 Server per Default eingebaut. Welche Version installiert ist, bekommen Sie mit "GET-HOST" heraus.

Powershell 2.0 Download für Windows XP SP2, 2003 SP2, 2008 und Vista SP1
968929 Windows Management-Frameworks (Windows PowerShell 2.0, WinRM 2.0 und BITS 4.0)

E-Book zu Powershell
https://blogs.technet.com/chitpro-de/archive/2007/05/10/english-version-of-windows-powershell-course-book-available-for-download.aspx
https://profile.microsoft.com/RegSysProfileCenter/wizard.aspx?wizid=adf74b41-ae6a-42f4-8445-db39ecabb8b3&lcid=2055&fu=http://download.microsoft.com/download/a/9/4/a94270c7-ed16-4c72-8280-658c66315719/Windows%20Powershell%20-%20EN.zip

Windows PowerShell Graphical Help File (Version 2.0)
http://www.microsoft.com/downloads/details.aspx?familyid=FEFB2572-559A-46FE-978D-5A00490B20FA&displaylang=en
Windows PowerShell Quick Reference
http://www.microsoft.com/downloads/details.aspx?FamilyID=df8ed469-9007-401c-85e7-46649a32d0e0&DisplayLang=en
Windows PowerShell 1.0 Documentation Pack
http://www.microsoft.com/downloads/details.aspx?FamilyID=b4720b00-9a66-430f-bd56-ec48bfca154f&DisplayLang=en

Bislang hatten wir Administratoren nur die Möglichkeit, diverse Tätigkeiten über selbst entwickelte VBScript-Programme (Einige dazu finden Sie auf Franks Tools) oder Kommandozeilenprogrammen (LDIFDE, CSVDE etc.) verschiedene Aktionen zu automatisieren. Das hatte die Nachteile, dass zum einen nicht alle Objekte über Skriptsprachen erreichbar waren (z.B. Mailboxrechte kann man per VBScript erst seit Exchange 2000 SP2 setzen) und zudem gerade VBScript sehr langen und teilweise auch unübersichtlichen Code produziert hat. Das lag natürlich auch an den verschiedenen Schnittstellen, die angesprochen werden mussten.

Entsprechend aufwändig und vor allem inhomogen war die Nutzung verschiedener Konfigurationen per Script. Gerade beim Anlegen von Exchange Benutzern (Siehe WSH - Benutzer mit Postfach anlegen) wird schnell deutlich, wie fehleranfällig und aufwändig das alles wird.

Mit der PowerShell wird nun alles etwas anders, da die PowerShell aus meiner Sicht die klassische "DOS-Box" als Eingabemedium für administrative Zwecke verdrängen wird. Zum Anderen mehren sich die Zeichen, dass die PowerShell als Abstraktionsebene zwischen grafischen Oberflächen und dem System werden wird. So gibt es GUIs geben, die nicht mehr direkt die Konfigurationsänderungen am System durchführen, sondern ihrerseits einfach nur Funktionen der PowerShell aufrufen. Microsoft und auch Dritthersteller können quasi die PowerShell als Vermittler zwischen dem Administrator und dem System verwenden. Dazu wird die PowerShell umfangreich durch eigene Funktionen und Commandlets erweiterbar sein.

Aber auch schon die eingebaute Funktionen sind für einen Administrator eine echte Hilfe, um Konfigurationsänderungen aber auch Auswertungen sowohl  automatisiert als auch interaktiv durchzuführen. Es ein Zwischending zwischen einer Shell wie die CMD.EXE, der Unix Shell und Skriptsprachen wie Perl mit sehr mächtigen und zugleich einfachen Funktionen zur Automatisierung.

Interessant ist, dass die Shell eine Hilfe und quasi MAN-Pages anbietet, dass Funktionen mit einem Alias belegt werden können und umfangreiche Import- und Exportfunktionen (CSV, HTML, XML) bereitstehen, um Daten zu schreiben oder als Quelle für eigene Befehle zu importieren.

PowerShell und Auditing

Je mehr Anwendungen und Konfigurationsänderungen über die PowerShell erfolgen, desto eher kommt der Wunsch auf, diese Aktionen auch zu protokollieren. Über einen Schlüssel in der Registrierung lässt sich dies tatsächlich zumindest für die Exchange Commandlets erreichen. Der Wert kann natürlich per PowerShell selbst gesetzt werden.

set-itemproperty HKLM:\SOFTWARE\Microsoft\PowerShell\1\PowerShellSnapIns\Microsoft.Exchange.Management.Msh.Admin -Name LogpipelineExecutionDetails -value 1

Leider weiß ich nicht, wie man dies "global" aktivieren könnte, d.h. dass PowerShell wirklich jede aufgerufene Option protokolliert. Aber schon die Protokollfunktion für Exchange ist natürlich sehr nütztlich. Am besten schalten Sie diesen Eintrag ebenfalls über eine Gruppenrichtlinie für alle Systeme ein, auf denen die Exchange Management Tools installiert sind. Eine passende ADM-Vorlage finden Sie hier zum Download.

Vorlage für Gruppenrichtlinien
EnablePS1ExchangeLogging.adm

REG-Datei zum Import z.B. per StartupScript, Softwareverteilung
enable_ps1_exchangelogging.reg

Nach der Installation finden Sie dann jede Aktion der Exchange Management Shell im "Windows PowerShell"-Eventlog.

So ist zumindest hinsichtlich Exchange eine Protokollierung möglich. Wenn Sie dann ihr System mit einen Tool zum Einsammeln von Eventlog-Meldungen kombinieren (z.B. MOM), dann haben sie schon eine recht gute Protokollierung und Dokumentation, was in ihrer Umgebung passiert. Allerdings kann eine berechtigte Person natürlich immer noch an der PowerShell vorbei Änderungen in der Konfiguration vornehmen, z. B: durch LDP, ADSIEDIT, RegEdit etc.

Ein paar PowerShell Befehle

Die PowerShell steht noch am Anfang der Entwicklung aber ein paar Befehle sind schon sehr interessant und zeigen die Funktionsweise und Brauchbarkeit:

dir drivers:
ls hkcu:\software\m*
get-process
get-progress | where {$_handles -ge 100}

Die Ausgabe kann ebenfalls umfangreich kontrolliert werden. So können die Ausgaben mit derm PIPE (|) Symbol an folgende Befehle weitergeleitet werden

Schauen Sie einfach mal im Internet nach weiteren Beispielen der PowerShell.

Ausgabe der Methoden einer .NET-Klasse mit der Funktion "getconstructors" der Powershell:

PS C:\> [system.net.mail.attachment].getconstructors() | foreach-object {$_.tostring()}

Ausgabe:
Void .ctor(System.String)
Void .ctor(System.String, System.String)
Void .ctor(System.String, System.Net.Mime.ContentType)
Void .ctor(System.IO.Stream, System.String)
Void .ctor(System.IO.Stream, System.String, System.String)
Void .ctor(System.IO.Stream, System.Net.Mime.ContentType)

PS1-Dateien starten

Nun kann man mehrere Powershell-Kommandos natürlich auch in einer PS1-Datei zusammenfassen. Das müssen nicht nur "einfache" Aufrufe sein, sondern können komplette Skripte mit Funktionen und Routinen sein. Allerdings werden Sie feststellen, dass ein "Doppelklick" auf eine PS1-Datei einfach nur Notepad startet und nicht das Skript.

Sie müssen das Skript wirklich über die Powershell starten. Und selbst da reicht es nicht, wenn Sie einfach den Namen des Skripts auf der Kommandozeile direkt eingeben. Powershell interpretiert dies dann einfach als String, den sie 1:1 ausgibt.

Um ein Skript im aktuellen Verzeichnis zu starten, müssen Sie ein ".\" davor schreiben. Ein Skript in einem anderen Verzeichnis startet man mit einem "&" davor

PS C:\>.\skriptimaktuellenVerzeichnis.ps1

PS C:\>& "c:\test\skriptname.ps1"

Wer mit UNIX schon etwas zu tun gehabt hat, wird dies schon kennen.

Powershell Performance

Oft beschweren sich Administratoren über die "langsame" Performance beim Start der Powershell. Das liegt oft daran, dass das .NET Framework erst entsprechende Module kompilieren muss. Das kann man mit einer kurzen Zeile auch schnell vorab machen:

# 64Bit System
Set-Alias ngen @(
   dir (join-path ${env:\windir} "Microsoft.NET\Framework64") ngen.exe -recurse |
   sort -descending lastwritetime)[0].fullName
   [appdomain]::currentdomain.getassemblies() | %{ngen $_.location}
# 32bit Systeme
Set-Alias ngen @(
   dir (join-path ${env:\windir} "Microsoft.NET\Framework") ngen.exe -recurse |
   sort -descending lastwritetime)[0].fullName
   [appdomain]::currentdomain.getassemblies() | %{ngen $_.location}

Damit werden die Komponenten schon kompiliert und im Global Assembly Cache (GAC) abgelegt. Allerdings muss man das natürlich als Administrator ausführen.

E2K7 APIs

Wie ernst es Microsoft mit der PowerShell meint, zeigt die Liste der API's und deren Veränderungen mit Exchange 2007 auf http://msexchangeteam.com//archive/2005/09/15/410941.aspx

API Wird ersetzt durch
ExWin32 (aka M: or IFS) Web Services
EDK Gateway Managed Agents
Transport Event Sinks Managed Agents
CDOExM PowerShell  “cmdlets”
WMI PowerShell  “cmdlets”
CDOWF Windows Workflow Foundation
Web Forms ASP.net
MAPI unverändert

Auch das Exchange Team Blog mischt kräftig mit:

Powershell Erweiterungen

Gerade die Commandlets von Powershell erlauben es, dass man auch als Entwickler oder Admin eigene Module entwickelt und mit einbindet. Den gleichen Weg geht ja z.B.  Exchange 2007 auch. Und es gibt noch Platz für Powershell Erweiterungen.

Powershell Skripte erstellen

Natürlich ist die Powershell nicht nur eine Konsole zur Eingabe von "One-Liners", also Befehlen, die in eine Zeile passen. Die Powershell kann komplette Skripte und Programme ausführen. Allerdings ist es sehr nervig, diese Skripte mit Notepad zu erstellen. Da lobe ich mir Entwicklungsumgebungen, die ein Debugging erlauben und bei der Eingabe schon die möglichen Optionen vorschlagen. Für die Powershell gibt es gleich mehrere kostenfreie und kommerzielle Optionen:

Powershell "beschleunigen mit NGEN

Viele Administratoren beschweren sich, dass die Powershell sehr lange zum Start braucht. Das wird um so länger, wenn weitere AddIns (wie z.B. Exchange) geladen werden müssen. Das Problem dabei ist, dass .NET-typisch noch nicht genutzte Module erst "kompiliert" werden müssen. Aus dem gleichen Grund braucht das Exchange Setup und Rollup Fixes lange, da auch hier nur vorkompilierte Assemblies installiert werden die beim Start oder durch NGEN während der Installation erst für das Zielsystem kompiliert werden.

Das kann man aber beschleunigen. Jeff Snovers hat auf seinem Blog die Hinweise und ein passendes Powershell-Skript veröffentlicht.

Set-Alias ngen @(
dir (join-path ${env:\windir} "Microsoft.NET\Framework") ngen.exe -recurse |
sort -descending lastwritetime
)[0].fullName
[appdomain]::currentdomain.getassemblies() | %{ngen $_.location}

Auf Windows 64bit Systemen muss man das Skript etwas anpassen:

Set-Alias ngen @(
dir (join-path ${env:\windir} "Microsoft.NET\Framework64") ngen.exe -recurse |
sort -descending lastwritetime
)[0].fullName
[appdomain]::currentdomain.getassemblies() | %{ngen $_.location}

Weitere Microsoft Links

Anleitungen und Kurse

Weitere Links

Keywords: PowerShell Monad Admin Scripting