PowerShell für Adminsistratoren

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
Administrator's Guide to PowerShell Remoting (Kostenfreies ebook)
http://PowerShell.com/cs/blogs/news/archive/2010/03/03/administrator-s-guide-to-PowerShell-remoting.aspx

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

Free eBooks
http://PowerShell.org/wp/ebooks/

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 `
   -path 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ützlich. 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

  • FT
    FT steht für "formatted Table" und erlaubt die Ausgabe als Tabelle mit der Angabe der gewünschten Felder etc.
  • Group
    gruppiert die Ausgabe, z.B. "| group company" gruppiert die Ergebnisse nach dem Feld "!company". Das funktioniert z.B. für Prozesse
  • Sort
    erlaubt die Sortierung der Ausgabe nach dem Alphabet aber auch nach der Menge des Auftretens etc.

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 können.

PowerShell History und Autocomplete

Wer PowerShell-Befehle eintippt, sollte öfters mal die TAB-Taste verwenden. An vielen Stellen komplettiert PowerShell dann den Wert, den Parameter oder das Commandlet. Ist die Auswahl nicht eindeutig, dann drücken Sie einfach mehrfach TAB um durchzulaufen. Mit "UMSCHALT-TAB" geht es wieder rückwärts.

Auch gibt es eine "History", die sie einfach mit "Pfeil hoch, Pfeil runter" aufrufen können. Weniger bekannt ist hier, dass über die Variable $MaxHistoryCount sogar die Größe dieses Puffers bestimmt werden kann. Zudem können Sie auch mit einem "#" als Prefix auf die History per Autocomplete zugreifen.

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, Lync auch. Dabei gibt es zwei Wege:

  • PSSnapIn
    Hierbei handelt es sich um die Erweiterung, wie Sie schon seit PowerShell1 verfügbar ist. Entsprechend kompilierte DLLs werden mit eingeladen.
  • Module
    Seit PowerShell 2 gibt es auch Module, die etwas flexibler sind. Es müssen z.B. nicht mehr DLLs sein sondern können auch einfache PS-Dateien (Erweiterung PS1M) sein, die damit zusätzliche Funktionen anbieten können.

Wenn die Module oder Snapins auf dem lokalen Rechner installiert sind, ist Anzeige und Einbindung sehr einfach.

Befehl Ergebnis

Get-PSSnapin -registered
Get-Module -listAvailable

Liste der installierten (auch nicht geladenen) Snapins anzeigen.

Add-PSSnapin name
Import-Module name

Angegebenes Snapin laden.

Get-Command -pssnapin name
Get-Command -module name

Anzeige der Befehle, die ein Snapin Bereit stellt.

Get-PSSnapin
Get-Module

Aktuell geladene Snapins anzeigen.

Wenn ich PowerShell-Skripte schreibe, will ich nicht immer den Administrator auffordern, die "richtige" PowerShell zu starten. Vor allem wenn Skripte sowohl Lync als auch Exchange benötigen, ist es praktischer die erforderlichen Snapins am Anfang zu laden.

# Exchange 2010 
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010

# Exchange 2007
Add-PSSnapin Microsoft.Exchange.Management.PowerShell.Admin

# Lync
Import-Module LYNC

# Active Directory
Import-Module ActiveDirectory

# Windows Server backup
Add-PSSnapin Windows.ServerBackup

Um Fehlermeldungen zu umgehen, kann man vorher prüfen, ob das Snapin schon geladen ist.

function LoadExchangeSnapin
{
    if (! (Get-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 -ErrorAction:SilentlyContinue) )
    {
        Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010
    }
}

Bitte laden Sie aber nur die Snapins, die installiert sind und benötigt werden.

Und es gibt noch Platz für PowerShell Erweiterungen.

PowerShell remote verwenden

Sowohl Exchange als auch Lync nutzen alternative Wege, remote zu verwalten. Beide addieren ein virtuelles Verzeichnis im IIS, gegen welche sich eine PowerShell verbinden kann.

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 "planen"

PowerShell-Skripte können wie jedes andere Programm und Skript natürlich auch einfach über den Taskplaner regelmäßig ausgeführt werden. Sie starten einfach die "PowerShell.exe" und übergeben das gewünschte Kommando. Ein direkter Aufruf von PS1-Dateien würde sonst nur den Notepad oder einen anderen Default-Editor öffnen.

C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe 
   -command "get-process"

Der String hinter "Command" ist einfach PowerShell, d.h. das kann ein einzelnes Commandlet oder eine Serie von Befehlen (durch ";" getrennt) sein.Wer dann natürlich noch Exchange-Befehle absetzen will, muss dafür sorgen, dass die Exchange LaufzeitUmgebung mit geladen wird.

C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe 
   -command ". 'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1';
                Connect-ExchangeServer -auto;
                get-mailboxdatabase"

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 müssen Sie 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}

PowerShell und mobile Geräte

Gleich vorneweg: Es gibt keine PowerShell für Windows Mobile oder sonst ein mobiles Gerät. Aber das heißt ja nicht, dass man nicht doch von einem Smartphone auf einem Server einen "PowerShell-befehl" ausführen kann. Schon Exchange 2010 erlaubt per OWA diverse Dinge wie Messagetracking oder Pflege von Gruppenmitgliedschaften. Andere haben auch schon Ideen veröffentlicht:

Natürlich könnte man auch eine kleine APP schreiben, die per HTTPs einen Webservice anspricht, der dann gewünschten Aktionen ausführt.

Weitere Microsoft Links

Anleitungen und Kurse

Weitere Links