PowerShell Beispiele
Microsoft Consultant Exchange & Skype for Business (m/w)
Kommen Sie zu Net at Work. Wir haben spannende Projekte bei innovativen Kunden. Unser Team arbeitet kollegial und kooperativ – ständiger Austausch und Weiterbildung sind bei uns Standard.
https://www.netatwork.de/unternehmen/karriere/
Es ist sicher nichts neues, dass die PowerShell ein wichtiges Werkzeug des Exchange 2007 Administrators ist. Aber auch außerhalb von Exchange ist die PowerShell so nützlich, dass ich heute auf die "DOS-Box" Verzichte und gleich die PowerShell nutzen. Auch wenn es nicht um Exchange geht. Um die Einsatzbereiche hier besser deutlich zu machen, versuche ich auf dieser Seite all die Tipps und Codeschnipsel zu sammeln, die ich selbst auch immer wieder einsetze. Es sind keine komplette Programme, sondern Bausteine und Vorlagen.
WSV301 Windows PowerShell für Beginners
http://www.msteched.com/2010/Europe/WSV301
Mastering PowerShell
http://PowerShell.com/Mastering-PowerShell.pdf
Layman's guide to PowerShell 2.0 remoting
http://www.ravichaganti.com/blog/?p=1780
PowerShell Cookbook
http://www.pavleck.net/PowerShell-cookbook/
Befehle und mehrere Zeilen
Wenn man einen Befehl in mehreren Zeilen aufteilen will, weil er dann besser "lesbar" ist, dann muss man den BackTick (`) als Zeilenendezeichen verwenden, welches aber durch ein Leerzeichen abgetrennt sein muss. In VBScript wurde dazu der underscore "_" am Zeilenende genutzt.
# Beispiel einer lesbaren Zeile mit umbruechen set-mailbox ` -identity frank.carius ` -PrimaryEmailAddress "test@msxfaq.de"
Es dient der Übersichtlichkeit, wenn man das reguläre Ende einer PowerShell Zeile mit einem Semikolon (;) abschließt. Die "Pascal-Programmierer" von Früher werden sich hier wieder erinnern.
Der "BackTick" hat aber auch noch die Funktion, besondere Steuerzeichen einfach einzugeben, z.B.: ein "LineFeed" und ersetzen damit das "vbCRLF" aus VBScript/VBA-Zeiten:
0 Null `a Benachrichtigung `b Rückschritt `f Seitenvorschub `n Zeilenwechsel `r WagenRücklauf `t Horizontaler Tabstopp `v Vertikaler Tabstopp
Damit lassen sich auch einfach String[]-Arrays, die man bei einem "get-content" bekommt, in einen mehrzeiligen String konvertieren:
$body = get-content $bodyfile $body = [string]::Join("`r`n",$body)
PowerShell und Dokumentation
Selbst die kleinsten Programmschnipsel und Skripte sollten ein Mindestmaß an Dokumentation enthalten. In PowerShell können einzelne Zeilen einfach durch die Raute (#) auskommentiert werden.
# Das ist eine einzelne Dokumentationszeile
Es gibt eigentlich keine Entschuldigung, wenn ein Entwickler die Dokumentation einspart außer dass er ein schlechter Entwickler ist. Seit der PowerShell 2 gibt es sogar eine Struktur, mit der Sie selbst ihre Skripte dokumentieren können, so dass die PowerShell diese Hilfe auch verwenden kann:
<# .SYNOPSIS Retrieves service pack and operating system information from one or more remote computers. .DESCRIPTION The Get-Inventory function uses Windows Management Instrumentation (WMI) ... .PARAMETER computerNameAccepts a single computer name or an array of computer names .PARAMETER path The path and file name of a text file. Any computers that cannot be reached will be logged to this file. .EXAMPLE Read computer names from Active Directory and retrieve their inventory information. Get-ADComputer -filter * | Select{Name="computerName";Expression={$_.Name}} | Get-Inventory .EXAMPLER ead computer names from a file (one name per line) and retrieve their inventory information Get-Content c:\names.txt | Get-Inventory .NOTES You need to run this function as a member of the Domain Administratoren group. #>
Nur schreiben müssen Sie die Dokumentation und den Code natürlich noch selbst.
- WTFM: Das Handbuch gehört dazu
http://technet.microsoft.com/de-de/magazine/ff458353.aspx
PowerShell und Tastatureingaben für Pause
Es ist gar nicht so einfach, ein "PAUSE" zu machen, wie dies in BAT und CMD-Dateien schon immer möglich ist. Es gibt gar mehrere Optionen aber eine kommt da wohl am nächsten dran:
function Pause ($Message="Press any key to continue...") # Quelle https://blogs.msdn.com/b/PowerShell/archive/2007/02/25/pause.aspx { Write-Host -NoNewLine $Message #$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") Write-Host "" }
Alternativ können Sie Auch den gesamten Puffer mit $Host.UI.RawUI.FlushInputBuffer() leeren.
- Wait für Key Press
http://PowerShell.com/cs/blogs/tips/archive/2009/07/08/wait-for-key-press.aspx - DEMO: Trap Ctrl+C by Joel
Bennett
http://poshcode.org/542 - Windows PowerShell Tip of
the Week - using a Script until
the User Presses a Key
http://technet.microsoft.com/en-us/library/ff730938.aspx
Messagebox und Nachfrage
Im Gegensatz zu VBScript kann die PowerShell nicht direkt eine "Messagebox" auf den Bildschirm bringen. Aber über den Umweg ein COM-Objekt zu instanziieren, geht es dann doch:
$wshshell = new-object -comobject wscript.shell $Answer = $wshshell.popup("Mitteilung",0,"Kopfzeile",4)
Die erste Zahl definiert dabei den Timeout, ab wann die Messagebox alleine "zusagt" und die vierte Stelle bestimmt die Buttons. Spielen Sie einfach etwas interaktiv damit herum. Alternativ kann man sich natürlich auch dem .NET Framework bedienen:
[void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms") $result = [windows.forms.messagebox]::Show("Meldung","Kopfzeile")
Wenn Sie keine Eingabe per Messagebox möchte, sondern auf der Kommandozeile eine Tastatureingabe anfordern wollen, dann ist "Read-Host" ihr Freund:
Einfache Eingaben können So auf der Konsole abgefragt werden. Allerdings wartet "Read-Host" immer ein "CRLF" am Ende ab, d.h. der Code steht bis sie eine Eingabe gemacht haben.
Reagieren auf Tastatureingabe mit $Host.UI.RawUI oder [console]
Über das "$host"-Objekt können Sie sogar prüfen, ob gerade eine Tastatureingabe an den Prozess "ansteht" und auch diese Taste dann abrufen.
if ($host.UI.RawUI.KeyAvailable) {
$taste = $host.UI.RawUI.ReadKey()
write-host "Tastendruck erkannt $taste" }
Statt $host.UI.RawUI" können Sie auch den Kurzcode [console] nutzen.
if ([console]::KeyAvailable) { $taste = [console]::ReadKey() write-host "Tastendruck erkannt $taste" }
ReadKey wartet aber, bis ein Tastendruck angekommen ist, d.h. sie müssen schon vorher auf KeyAvailible prüfen. Um z.B. in einer Schleife auf Tasten zu reagieren ohne den Code anzuhalten.
Achtung: Readkey kommt auch bei "Halbtasten" zurück, z.B. wenn die die ALT-Taste auch nur drücken, um ,mit "ALT-TAB" in ein anderes Fenster zu springen.
- Windows PowerShell Tip of the Week
https://technet.microsoft.com/en-us/library/ff730938.aspx - PowerShell: Pause for specific key
strokes
https://gavinb.net/2012/08/09/powershell-pause-for-specific-key-strokes/ - How to properly pause a Powershell
Script
https://adamstech.wordpress.com/2011/05/12/how-to-properly-pause-a-powershell-script/
Ping mit PowerShell
Wenn man nicht gleich wieder das "PING.EXE" als Prozess starten will, können Sie auch per PowerShell über WMI einen PING absetzen, .z.B. mit
$Pingresult = Get-WmiObject -Class Win32_PingStatus
-Filter "Address='servername'"
if ($Pingresult.statuscode -eq 0) {
Write-Host "Ping erfolgreich"
}
Ein Statuscode von "0" meldet einen erfolgreichen PING. Viel einfacher ist aber natürlich das passende Commandlet
Test-Connection -computername srv01
PowerShell tönt
Auch die Ausgabe von Tönen ist möglich. Hierzu gibt es sogar eine ganze Menge von Optionen. Vom einfachen "Biep" bis zu Systemsounds und ganzen Audiodateien.
# Minimalistischer Piep write-host `a # einfach nur Piep" [System.Console]::Beep() [System.Console]::Beep(1000,300) # erste Zahl ist die Frequenz in Hz, die Zeite Zahl die Dauer # System Sounds verwenden [system.media.systemsounds]::Beep.play() [system.media.systemsounds]::Asterisk.play() [system.media.systemsounds]::Exclamation.play() [system.media.systemsounds]::Hand.play() [system.media.systemsounds]::Question.play() #Sound mit MediaPlayer wiedergeben $mplay=New-Object -ComObject 'Mediaplayer.Mediaplayer' $mplay.Filename=$Filename $mplay.Play()
Es sollten also genug Spielraum von einem Lebenszeichen bis zur kompletten Steuerung einer Audioausgabe.
- Win32-Funktionen in
PowerShell-Skripten nutzen
http://heise.de/-2405660
Ein Beispiel, wie sie auch mit der WIn32-API ein BEEP machen können.
Code auf ftp://ftp.heise.de/pub/ct/listings/1422-178.zip
Testmails versenden
Das folgende Skript versendet 100 Mails und schreibt die laufende Nummer mit in den betreff. Das ist ideal, um die Laufzeit von Mails zu müssen, die Leitwegewahl zu prüfen oder auch einfach Verluste und Aussetzer bei Cluster und NLB-Konfigurationen zu erkennen.
# fillout the parameters and go $SmtpClient = new-object system.net.mail.smtpClient $SmtpClient.Host = "smarthost" # Optional with SSL and Authentication $SmtpClient.EnableSsl = $true $SmtpClient.Credentials= New-Object System.Net.NetworkCredential($smtpUser, $smtppass) foreach ($count in (1..50)) { write-host "Sending Mail $count" $MailMessage = New-Object system.net.mail.mailmessage $mailmessage.from = ("sender@firma.tld") $mailmessage.To.add("empfaenger@firma.tld") $mailmessage.Subject = "MSXFAQ SMTPSTORM.PS1 $count" $mailmessage.Body = "MSXFAQ SMTPSTORM.PS1 $count" $smtpclient.Send($mailmessage) }
Das ist natürlich ein einfaches Beispiel, wie man eine Klasse des .NET Frameworks direkt verwenden kann und mit einer schnellen For-Schleife kombiniert. Die Klasse kann das sogar per SSL und mit Authentifizierung:
Mit PowerShell 2 ist dies jedoch noch weiter vereinfacht worden, weil es nun einfach ein "Send-MailMessage"-Commandlet gibt.
- Send-MailMessage
http://technet.microsoft.com/de-de/library/dd347693.aspx
send-mailmessage ` -smtpServer mail.example.com ` -from "User01@example.com" ` -to "User02@example.com ", "User03@example.com " ` -subject "Betreff der Nachricht" ` -body "Dies ist der Nachrichteninhalt" ` -Attachment "anlage1.txt" ` -priority High ` -dno onSuccess, onFailure
Natürlich müssen nicht alle Parameter angegeben werden. Wer mag kann natürlich auch weiterhin "CDO" verwenden. Dazu muss aber CDO lokal installiert sein, z.B. in Form des Windows 2003 virtuellen SMTP-Servers.
$mail = new-object -comobject "cdo.message" $mail.From = "Sender@example.com" $mail.To = "recipient@example.com" $mail.Subject = "Betreff" $mail.TextBody = "Dies ist der Textbody" $mail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2 $mail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.sample.com" $mail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25 $mail.Configuration.Fields.Update() $mail.Send()
Schöner ist aber schon der Ansatz über die .NET Klasse, da man damit komplett auf CDO verzichten kann.
Dateien per HTTP automatisiert übertragen
Diese Beispiel nutzt den WebClient von .NET, um eine Datei von einem Webserver herunter zu laden, die in einer CSV-Datei hinterlegt sind. Natürlich kann man das Beispiel auch mit einer Datei ganz ohne CSV-Datei schreiben. Aber so sehen Sie, wie eine externe Datendatei einfach importiert werden kann.
$clnt = new-object system.net.webclient $colFiles = Import-csv C:\temp\DL.csv foreach ($file in $colFiles) { $clnt.DownloadFile($file.QuellURL, $file.Ziel) }Inhalt der CSV-Datei.priv:
QuellURL,Ziel http://www.msxfaq.net/sitemap.xml,c:\temp\sitemap.xml http://www.msxfaq.net/index.htm,c:\temp\index.htm
Diese Funktion kann z.B. interessant sein, wenn Sie für einen Verzeichnisabgleich Dateien abholen wollen.
Mit PowerShell 3.0 gibt es ein Commandlet "Invoke-WebRequest"
- Invoke-WebRequest
http://technet.microsoft.com/en-us/library/hh849901.aspx - PowerShell v3.0:
Invoke-WebRequest
http://psscripts.blogspot.de/2012/09/PowerShell-v30-invoke-webrequest.html
TAIL mit Filesystemwatcher
Hinweis:
Ich habe ein Programm basierend auf dieser
Funktion geschrieben, welches ans Ende springt
oder sich sogar die letzte Position merkt. Siehe
Get-Tail.
Mit PowerShell 3 ist das Commandlet "Get-Content" leistungsfähiger geworden und kann nun auch direkt ans Ende springen oder sogar eine vorgegebene Anzahl von Zeilen zurück lesen und warten.
Eine weitere Funktion eines Skripts kann es sein, Dateien in einem Verzeichnis auf Veränderungen zu �überwachen, z.B. Um einen Echtzeitstatus von IISLogs oder Message Tracking Logs zur Auswertung zu erhalten. Auch hier hilft PowerShell und das .NET Framework mit fertigen Klassen weiter:
$FileSystemWatcher = New-object System.IO.FileSystemWatcher "c:\temp" $result = $FileSystemWatcher.WaitForChanged("all")
Das Skript wartet also auf eine beliebige Änderung im Verzeichnis und kehrt auch erst dann zurück. Die Ausgabe von $result enthält
Natürlich kann man durch die Angabe einer Zeit ("all",10000) nach 10 Sekunden eine Rückkehr erzwingen oder gleich über Events arbeiten.
Get-Tail
PowerShell Script
-
Tail
Tools für TAIL - MSH directory watcher with popup-balloon
ttp://mow001.blogspot.com/2005/10/msh-directory-watcher-with-popup.html - PSEventing 0.5 Beta
http://www.codeplex.com/PSEventing/Wiki/View.aspx?title=Home&version=22
Trap and respond to synchronous & asynchronous .NET, COM and WMI events within your PowerShell scripts with this easy to use suite of cmdlets - Directory Mirror using the FileSystemWatcher class
http://www.codeproject.com/KB/files/directorymirror.aspx - MSDN Beschreibung
http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx
Aktueller Benutzer ermitteln
Solche Funktionen sind natürlich besonders interessant, wenn z.B. PowerShell für Automatisierungen, Anmeldeskripte o.ä., genutzt wird. Dabei hilft natürlich wieder .NET mit der Klasse "[System.Security.Principal.WindowsIdentity]::GetCurrent()" und ihren Properties.
PS C:\>[System.Security.Principal.WindowsIdentity]::GetCurrent() AuthenticationType : Kerberos ImpersonationLevel : None IsAuthenticated : True IsGuest : False IsSystem : False IsAnonymous : False Name : MSXFAQ\fcarius Owner : S-1-5-21-19119449-30417519-71842111-1009 User : S-1-5-21-19119449-30417519-71842111-1009 Groups : {S-1-5-21-19119449-30417519-71842111-513, S-1-1-0, S-1-5-21-1894181349-4012846640-3243972333-1008, S-1-5-32-545...} Token : 2268
Wie sie sehen ist es ganz einfach den aktuellen Benutzernamen und die Anmeldung zu ermitteln. Sogar die "Tokensize" ist direkt ablesbar. Mit wenigen weiteren Funktionen lassen Sich z.B. die SIDs der Gruppen entsprechend konvertieren. Denn jede Gruppe in der Auflistung "Groups" hat wiederum eine "Translate"-Methode.
$group = [System.Security.Principal.WindowsIdentity]::GetCurrent().groups[0] Write-host "Erster Gruppe:" $group.Translate([System.Security.Principal.NTAccount]).tostring()
- WindowsIdentity.GetCurrent
Method
http://msdn.microsoft.com/de-de/library/system.security.principal.windowsidentity.getcurrent.aspx - Gruppen eines Benutzers
auslesen
http://csharp-tricks.blogspot.de/2010/06/gruppen-eines-benutzers-ermitteln.html
Funktionen und "RETURN"
Alle Ausgaben, die eine Funktion quasi "in die Pipeline" sendet, werden von dem aufrufenden Code als Rückgabe bewertet. In anderen Programmiersprachen ist man es gewohnt entweder schon bei der Deklaration die Variable zu kennzeichnen, die Rückgaben enthalten (By Ref) oder am Ende die Rückgabe explizit zu �übergeben. Bei PowerShell hingegen werden alle Ausgaben als Rückgabe gesendet.
Sie können natürlich in der PowerShell auch über das "RETURN"-Statement einen Block sofort verlassen und dabei sogar noch Parameter mit geben. Dieser Aufruf sorgt aber nicht dafür, dass "nur" diese Daten zurück übergeben werden.
- about_Return
http://technet.microsoft.com/en-us/library/hh847760.aspx - Effective PowerShell Item 7: understanding
Output
http://rkeithhill.wordpress.com/2007/09/16/effective-PowerShell-item-7-understanding-output/ - PowerShell: Watch Those
Implicit Return Values!
http://thepursuitofalife.com/PowerShell-watch-those-implicit-return-values/ - Return statement
http://en.wikipedia.org/wiki/Return_statement
Abfragen mit IF und Switch
Verzeigungen gehören zu den Regelfunktionen und PowerShell bietet hier auch neben dem klassischen IF-Strukturen auch SWITCH
if (bedingung) { Code } elseif (bedingung) { code } else { code }
Übersichtlicher sind aber SWITCH Anweisungen, insbesondere wenn Sie viele Werte vergleich müssen
switch ($variable) { "wert1" {code} "wert2" {code} "wert3" {code} default {code} }
Sie sind aber nicht auf einen Wert je Zeile beschränkt. PowerShell erlaubt auch die Angabe von Wildcards und RexEx-Ausdrücken, wenn Sie diese beim Switch-Befehl mit angeben.
switch -wildcard($variable) { "a*" {code} "b*" {code} "c*" {code} } switch -regex ($variable) { "wert1" {code} "wert2" {code} "wert3" {code} }
Interessant ist aber auch die direkte Auswertung in Formeln, da der Wert als "_$" mit übergeben wird.
switch ($variable) { {'wert1','wert2','wert3' -contains $_} { code} {'wert4','wert5','wert6' -contains $_} { code} {'wert7','wert8' -contains $_} { code} }
So lassen sich auch einfach mehrere Werte mit dem gleichen Code bearbeiten.
- Windows PowerShell Tip of
the Week : Switch Statement
http://technet.microsoft.com/en-us/library/ff730937.aspx - PowerShell SWITCH statement
with multiple values für a
single target choice
http://www.sevecek.com/EnglishPages/Lists/Posts/Post.aspx?ID=19
For-Schleife mit "$null"
Manchmal bekommt man Dinge, die glaubt man erst mal nicht. Oft erhält man als Ergebnis einer Aktion eine Liste, die man mit einer "ForEach"-Schleife gerne abarbeiten möchte. Das funktioniert, solange es wirklich eine Aufzählung ist. Interessant wird es aber, wenn das Ergebnis "$null" ist, wie das folgende Beispiel beweist:
foreach ($wert in $null) { write-host "wird doch ausgefuehrt" }
Der Code-Teil in der Schleife wird tatsächlich einmal ausgeführt. Da muss man dran denken und entweder vorher ein "$null" abfragen oder in der Schleife drin den Sonderfall abfangen. Oder sie setzen den Wert der Schleifenvariable vorher mit "@()" auf eine leere Liste. Trotzdem würde ich das als "unerwartet" ansehen.
Hinweis
Mittlerweile (PS5?) durchläuft eine Schleife nicht mehr eine
Null-Liste. Eine Sonderbehandlung ist dann nicht mehr
erforderlich.
- http://blogs.msdn.com/b/PowerShell/archive/2007/01/23/array-literals-in-PowerShell.aspx
- http://PowerShellcrashkurs.wordpress.com/2009/07/08/geheimnisvolle-PowerShell-teil-3-wenn-null-doch-etwas-ist/
PowerShell und Registry
Über einen PSDrive-Provider ist ein direkter Zugriff auf die Registrierung möglich
PS HKLM:\> Get-PSDrive Name used (GB) Free (GB) Provider Root ---- --------- --------- -------- ---- HKCU Registry HKEY_CURRENT_User HKLM Registry HKEY_LOCAL_MACHINE
Entsprechen kann direkt per *-Item und *-Itemproperty darauf zugegriffen werden. Hier ein paar Beispiele. Allerdings sind alle Einträge, also sowohl die Werte aus auch die schlüssel erst mal Objekte.
# Anlegen eines Keys New-Item -type directory HKCU:\Test Get-Item HKCU:\test # Wert setzen New-ItemProperty HKCU:\test -Name parameter -value 59322 -propertyType dword Get-ItemProperty HKCU:\Test\Parameter #Und wieder aufraeumen Remove-ItemProperty HKCU:\Test\ -name Parameter remove-Item HKCU:\test
Allerdings können Sie auch direkte die .NET Funktionen nutzen.
[Microsoft.Win32.Registry]::GetValue("HKEY_CURRENT_User\Environment", "Temp",$null);
- Registry-Klasse
http://msdn.microsoft.com/de-de/library/microsoft.win32.registry(v=vs.110).aspx - Registry.GetValue-Methode
http://msdn.microsoft.com/de-de/library/microsoft.win32.registry.getvalue(v=vs.110).aspx - Registry.SetValue-Methode
http://msdn.microsoft.com/de-de/library/microsoft.win32.registry.setvalue(v=vs.110).aspx
PowerShell und Zertifikatspeicher
Wer sich die Ausgabe von Get-PSDrive mal genauer ansieht, erkennt auch einen "Cert:"-Provider.
PS C:\> Get-PSDrive Name used (GB) Free (GB) Provider ---- --------- --------- -------- cert Certificate PS C:\> cd cert: PS cert:\> dir Location : CurrentUser StoreNames : {SmartCardRoot, UserDS, AuthRoot, CA...} Location : LocalMachine StoreNames : {SmartCardRoot, AuthRoot, CA, Trust...} PS cert:\> Get-childitem -Path cert:\currentUser\my Directory: Microsoft.PowerShell.Security\Certificate::currentUser\my Thumbprint Subject ---------- ------- C577080F325940C811942507EE5ECCDF07BB7100 OU=EFS File Encryption Certificate, L=EFS, CN=Administrator
Über ein einfaches "CD CERT:" kommen Sie in den Zertifikatspeicher durchlaufen und auch hier mit Get-Item etc. die Objekte anschauen und natürlich auch verändern.
PowerShell und Zertifikate
Sie können aber mit der einfachen TCP-Klasse auch eine Verbindung zu einem Server aufbauen und das Zertifikat "abholen" und inspizieren. So können Sie recht einfach z.B. das Ablaufen von Zertifikaten erkennen:
- CheckSSL
http://www.zerrouki.com/checkssl/ - Testing Lync server 2013
external URLs from Lync clients
(external web service, meet,
office webapps, lyncdiscover and
dialin)
http://blogs.technet.com/b/nettracer/archive/2014/05/21/testing-lync-server-2013-external-URLs-from-lync-clients-external-web-service-meet-office-webapps-lyncdiscover-and-dialin.aspx
Export, Import und Convert
Eine der stärksten Funktionen der PowerShell sind die leistungsfähigen Commandlets zum Export und Import von Daten.
- Export-CSV und Import-CSV
Einfache Funktion, um Objekte als Listen auszugeben. Ideal für Benutzerlisten, Gruppen etc. zur weiteren Auswertung oder Import in Excel oder andere Datenbanken. Per Import wird eine CSV-Datei schon fast zum universellen Transferformat z.B. für Adressen und Kontakten. - ExportCliXML und Import-CLiXML
Die erzeugte XML-Datei ist nicht unbedingt einfach zu lesen, aber sowohl für "Imports" als auch zur automatischen Weiterverarbeitung oder Anzeige per Stylesheets geeignet. Hier ein Beispiele
<Objs Version="1.1" xmlns="http://schemas.microsoft.com/PowerShell/2004/04"> <Obj RefId="RefId-0"> <MS> <S N="ColumnA">Data1</S> <S N="ColumnB">Data2</S> <S N="ColumnC">Data3</S> </MS> </Obj> </Objs>
- Convert-HTML
Diese nur als "Export" nutzbare Funktion erzeugt aus den Daten eine einfache HTML-Datei, die auch direkt angezeigt werden kann.
Das Schöne ist, dann die Commandlets ebenfalls wieder "Objekte" liefern. Wenn man mit Export-CSV oder Export-CliXML die Ergebnisse eines Prozesses als Datei ablegt, kann man sie sehr einfach wieder importieren und weiterverwenden.
PowerShell und andere DLLs und Klassen
Ein großer Vorteil von PowerShell ist die Möglichkeit, jede .NET-DLL relativ einfach einzubinden und die darin enthaltenen Objekte zu nutzen. Auf PS Klassen habe ich zwar gezeigt, wie man mit einer Hilfskonstruktion auch eine Art Klasse in PowerShell selbst erstellen kann, aber ratsam ist dies nur für ganz kleine Aufgabenstellungen. Früher oder später sollten Sie doch in C# mit Visual Studio oder einer anderen Umgebung größere Aufgaben als DLL erstellen.
[Reflection.Assembly]::LoadFile("D:\mydll.dll")
$obj = [msxfaq.sampleclass]::Global.AnyBuddy
Oder Sie nutzen die Funktion direkt in PowerShell Klassen mit "Add-Type" zu erstellen.
- Add-Type
http://technet.microsoft.com/de-de/library/dd315241.aspx
Der neue Weg eine Klasse in PowerShell zu erstellen - PS Klassen
- Making Applications
Scriptable via PowerShell
http://blogs.msdn.com/b/PowerShell/archive/2007/08/29/making-applications-scriptable-via-PowerShell.aspx - MSH Logo - allowing Users to
extend its functionality
https://www.leeholmes.com/blog/2006/02/14/msh-logo-allowing-users-to-extend-its-functionality/ - PowerShell: Load assembly
without locking file
http://elegantcode.com/2009/12/22/PowerShell-load-assembly-without-locking-file/ - Vista - How to load / unload
DLL
http://www.vistax64.com/PowerShell/93465-how-load-unload-dll.html - CSharpCodeProvider-Klasse
http://msdn.microsoft.com/de-de/library/microsoft.csharp.csharpcodeprovider.aspx
Damit können Sie quasi C#-Code zur Laufzeit kompilieren und dann direkt als DLL verwenden. - Make your .Net application
support scripting - a practical
approach
http://osherove.com/blog/2004/2/17/make-your-net-application-support-scripting-a-practical-appr.html
PowerShell signieren und Execution Policy
Je nach Einstellung führt die PowerShell ein Skript gar nicht, mit einer Warnung oder ohne Rückfrage aus. Man kann die PowerShell nämlich anweisen, eine digitale Signatur eines Skripts zu prüfen und entsprechend die Ausführung zu erlauben oder zu unterbinden. Gesteuert wird das Verhalten über den Befehl "SET-ExecutionPolicy", welcher die Einstellung annimmt.
- Set-ExecutionPolicy Restricted
Es werden gar keine Skripte ausgeführt. Nur interaktive Befehle sind möglich - Set-ExecutionPolicy AllSigned
Alle ausgeführten Skripte müssen durch eine vertrauenswürdige Quelle signiert sein. Ansonsten erfolgt eine Rückfrage. Unsignierte Skripte werden nicht ausgeführt - Set-ExecutionPolicy RemoteSigned
Skripte werden ausgeführt. Vor Skripten, die per Internet Explorer o.ä. herunter geladen wurden (und damit einer Internet Zone zugewiesen sind) wird erwartet, dass Sie eine digitale Signatur haben. - Set-ExecutionPolicy unrestricted
Alle Skripte werden ausgeführt. Vor Skripten, die per Internet Explorer o.ä. herunter geladen wurden (und damit einer Internet Zone zugewiesen sind) wird gewarnt. Es wird keine digitale Signatur erwartet.
Über den Befehl "GET-EXECUTIONPOLICY" können Sie die aktuelle Einstellung abfragen.
Bei einem Windows 2008 R2 Domain Controller ist per Default die ExecutionPolicy auf "restricted" gestellt.
Die ExecutionPolicy ist ein einfacher Schutz um zu verhindern, dass ein Admin per Doppelklick Code aus unbekannten Quellen ausführt. Es ist aber ein umgehbarer Schutz. Selbst als Benutzer können Sie z.B. einfach "Powershell.exe -ExecutionPolicy Bypass" starten.
- 15 Ways to Bypass the PowerShell
Execution Policy
https://blog.netspi.com/15-ways-to-bypass-the-powershell-execution-policy/
PowerShell COM-Objekte
So leistungsfähig die direkt nutzbaren .NET-Klassen sind, so sind viele wichtige Losungen heute nur als COM-Objekte verfügbar. Dazu zählen natürlich Outlook, Word, Excel aber auch viele Hilfsprogramme, die über die COM-Schnittstelle einfach wieder zu verwenden sind. In den nächsten Abschnitten sehen Sie, wie PowerShell sogar für die einfache Ausgabe einer Messagebox den Windows Skripting Host missbrauchen muss.
Es ist sehr einfach, eine Instanz eines COM-Objekts zu erhalten. Weisen Sie es einfach zu:
$variable = new-object -com name_des.comobjects
Danach können Sie "fast" unbegrenzt über das COM-Objekt verfügen.
- PowerShell - Ask Merlin: a cool demo of using COM objects
http://community.bartdesmet.net/blogs/bart/archive/2006/12/02/PowerShell-_2D00_-Ask-Merlin_3A00_-a-cool-demo-of-using-COM-objects.aspx - Introduction to Scripting - COM Objects with PowerShell
http://www.computerperformance.co.uk/PowerShell/PowerShell_com.htm
Aber beachten Sie dazu auch den folgenden Abschnitt über STA und MTA
Single Thread Appartment (STA) und Multi Thread Appartment (MTA)
Durch den Einsatz von "Redemption" und anderen COM-Objekten wurde ich unfreiwillig auf einen maßgeblichen unterschied der PowerShell im Vergleich zu VBScript aufmerksam. Ein kleiner 5-Zeiler, welcher einfach nur per COM-Objekt eine Mailbox öffnet hat mich mehrere Stunden suche gekostet. Folgendes war passiert:
- VBScript funktioniert
- PowerShell liefert Fehler
- C# Konsolenanwendung liefert Fehler
- C# Windows Forms Anwendung funktioniert
Zuerst dachte ich, dass ein Skript ohne "Windows Form" natürlich auch keine "Windows Message Pump" hat, mit der die Fenster untereinander Meldungen senden können. Aber mit dem Entwickler von Redemption (gleiches Problem) und der PowerShell Newsgroup konnte ich dann die C# Konsolenanwendung "tauglich" machen. Mit einem "[STATHREAD]" vor "main" lief auch diese Anwendung durch.
Insofern scheint VBScript per Default immer im STA-Mode zu laufen, während PowerShell 1 per Default "MTA" nutzt. Erst PowerShell 2 kann man mit dem Parameter "-STA" in die Single Thread Betriebsart zwingen. Den Status kann man mit folgendem Befehl abfragen:
[System.Management.Automation.Runspaces.Runspace]::DefaultRunspace
Hier eine Beispielausgabe:
Auf dem PowerShell Blog wird eine alternative Lösung mit einem Commandlet "Invoke-Appartment" angeboten.
Folgendes kleines Skript prüft den aktuellen Betriebszustand und startet das Skript im STA-Mode neu, wenn dies erforderlich sein sollte.
if ($host.Runspace.ApartmentState -neq 'STA') { write-host "Script is not running in STA mode. Switching " $Script = $MyInvocation.MyCommand.Definition Start-Process PowerShell.exe -ArgumentList "-sta $Script" Exit }
Der Abschnitt kann einfach am Anfang des PowerShell-Skripts eingefügt werden.
- Thread.ApartmentState and PowerShell Execution Thread
http://blogs.msdn.com/PowerShell/archive/2007/03/23/thread-apartmentstate-and-PowerShell-execution-thread.aspx - Calling FolderBrowserDialog from a PowerShell script
http://www.manning-sandbox.com/thread.jspa?messageID=62451 - Checking -STA Mode
http://PowerShell.com/cs/blogs/tips/archive/2011/01/17/checking-sta-mode.aspx - http://www.cauldwell.net/patrick/blog/ResolvedCallingAzManThroughMMCGtPowerShell.aspx
- http://stackoverflow.com/questions/1508704/does-PowerShell-sta-mode-eliminate-sharepoint-memory-leak-issue
- http://stackoverflow.com/questions/127188/could-you-explain-sta-and-mta
32bit/64bit
Seit Exchange 2010 gibt es die Commandlets und Management Console nur noch als 64bit Version. für Exchange 2007 gab es noch 32bit Versionen. Als Administrator muss man sich aber dennoch mit solchen "Besonderheiten" herum schlagen, da Windows eine Funktion hat, um immer die "richtige" Version zu starten. Zumindest nach dem was Windows als "Richtig" ansieht. Wer also aus einem 32bit Programm heraus einfach "PowerShell.exe" aufruf, bekommt auch immer die 32bit Version. Startet man hingegen aus einer 64bit Umgebung die "PowerShell.exe", dann hat man auch eine 64bit PowerShell. Was mache ich aber nun, wenn ich aus einem 32bit Programm auch wirklich die 64bit Version einer PowerShell starten will, z.B. weil ich einen PRTG Custom Sensor schreiben will, der Exchange Funktionen nutzt? Wer nun etwas im Windows Verzeichnisbaum rumstöbert, wird mehrere "Powerhell.exe"-Dateien finden.
C:\Windows>dir PowerShell.exe /s Datenträger in Laufwerk C: ist NAWNBFC-C Volumeseriennummer: xxxx-xxxx Verzeichnis von C:\Windows\System32\WindowsPowerShell\v1.0 14.07.2009 02:39 473.600 PowerShell.exe 1 Datei(en), 473.600 Bytes Verzeichnis von C:\Windows\SysWOW64\WindowsPowerShell\v1.0 14.07.2009 02:14 452.608 PowerShell.exe 1 Datei(en), 452.608 Bytes
Wer nun aber glaubt er startet per direkter Pfadangabe einfach die "richtige" PowerShell, der Irrt. Hier mal ein Test unter Windows 7 64bit. Es kann zudem irritieren, dass das Verzeichnis "System32" die 64bit-Versionen beinhaltet während SysWOW64 den 32bit Code enthalt. Die folgende Tabelle soll zeigen, welches Ergebnis beim Aufruf der DLLs erhalten wird.
StartUmgebung | Aufruf von | Ergebnis |
---|---|---|
CME.EXE 64bit |
C:\Windows\System32\cmd.exe |
64bit CMD |
CME.EXE 64bit |
C:\Windows\SysWOW64\cmd.exe |
32bit CMD |
CME.EXE 64bit |
C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe |
64bit PS |
CME.EXE 64bit |
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\PowerShell.exe |
32bit PS |
CME.EXE 32bit |
C:\Windows\System32\cmd.exe |
32bit CMD ! |
CMD.EXE 32bit |
C:\Windows\SysWOW64\cmd.exe |
32bit CMD |
CMD.EXE 32bit |
C:\Windows\System32\WindowsPowerShell\v1.0\PowerShell.exe |
32bit PS ! |
CMD.EXE 32bit |
C:\Windows\SysWOW64\WindowsPowerShell\v1.0\PowerShell.exe |
32bit PS |
CMD.EXE 32bit |
C:\Windows\Sysnative\WindowsPowerShell\v1.0\PowerShell.exe |
64bit !! |
Interessant dabei ist, dass eine 64bit StartUmgebung bei Aufrufen der 32bit Versionen auch 32bit Umgebungen startet. Umgekehrt muss man aber den Spezialordner "SysNative" verwenden, da ansonsten ein 32bit Process zwar die 64bit Version aufrufen kann, aber der File System Redirector doch wieder die 32bit Version startet.
Welche Version der PowerShell gerade läuft, lässt sich mit der Größenbestimmung einer Variable einfach ermitteln.
if ([System.IntPtr]::Size -eq 8) { write-host 64,":64bit Session" } else { write-host 32,":32bit Session" }
[System.IntPtr]::Size hat den Wert 8 bei 64bit und den Wert 4 bei 32bit PowerShell.
You can temporarily disable
filesystem redirection around the call to
Process. Start, the appropriate API's to P/Invoke
are Wow64DisableWow64FsRedirection and
Wow64RevertWow64FsRedirection. Another option is
to use %windir%\sysnative, which is available on
Windows Vista and above.
Quelle: Verschiedene Beiträge in Newsgroups. Urheber nicht mehr auszumachen.
- File System Redirector
http://msdn.microsoft.com/en-us/library/aa384187(VS.85).aspx -
Wow64DisableWow64FsRedirection
function (Windows)
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365743(v=vs.85).aspx
PowerShell und GUIDs
An vielen Stellen unter Windows wird mit GUIDs gearbeitet. Diese aufgrund ihrer Länge eigentlich als "eindeutig" anzusehenden Nummer kommt bei RPC-Protokollen, COM+ Schnittstellen, Exchange Mailboxen, AD-Objekten und anderswo vor. PowerShell und .NET erlauben sehr viel einfacher als VBScript einen umgang damit. Ein paar Beispiele:
$objUser = [adsi]"GC://CN=Administrator,CN=Users,DC=msxfaq,DC=net" # Ausgabe der GUID als String $objUser.guid # Ausgabe als Array of byte $objUser.objectguid # Ausgabe als GUID mit Bindestrichen [guid]($objUser.guid) # Neue GUID erstellen [guid]::NewGuid()
- Guid Structure
http://msdn.microsoft.com/en-us/library/system.guid.aspx - Guid.NewGuid-Methode
http://msdn.microsoft.com/de-de/library/system.guid.newguid.aspx
PowerShell und Netzwerkadressen
Eine häufige Fragestellung ist die Ermittlung der lokalen IP-Adressen. Das geht zwar auch per WMI oder per IPCONFIG mit anschließendem Parsen der Ausgabe aber viel eleganter ist die Nutzung der richtigen .NET-Klasse. Dann ist das ein Einzeiler:
# Anzeige der IP-Adressen [Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces().GetIPProperties().UnicastAddresses # Anzeige der Netzwerkkarten [Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces() # Ist eine Netzwerkverbindung aktiv [Net.NetworkInformation.NetworkInterface]::GetIsNetworkAvailable()
Über den gleichen Weg können die DNS-Server ermittelt werden aber leider keine DNS-Abfragen gestellt werden. Das geht zwar über die Klasse "[net.dns]" aber dabei gibt es nur ganz wenige Methoden:
# welche IP-Adresse hat ein Hostname (A-Name oder CNAME) [net.dns]::GetHostAddresses("www.msxfaq.de") # Reverse Lookup von IP-Adresse zu Hostname [net.dns]::GetHostByAddress('80.66.20.22') HostName Aliases AddressList -------- ------- ----------- gate.netatwork.de {} {80.66.20.22}
Leider sind über diese Klasse keine generischen Abfragen z.B. nach MX-Record oder gar SRV-Records möglich.
- NetworkInterface-Klasse
http://msdn.microsoft.com/DE-DE/library/system.net.networkinformation.networkinterface.aspx - Dns-Klasse
http://msdn.microsoft.com/de-De/library/system.net.dns.aspx - Dns-Klasse -Methoden
http://msdn.microsoft.com/de-de/library/system.net.dns_methods(v=vs.110).aspx
PowerShell und Klassen
Siehe dazu auch PS Klassen
In VBScript gibt die die Möglichkeit, Klassen zu definieren und damit Code hinter Objekten zu verstecken und vor allem bestimmte andere Teile aktiv zu halten (z.B. eine LDAP-Verbindung). Das Prinzip der objektorientierten Entwicklung hat die früher oft genutzte prozedurale Programmierung (Funktionen und Prozeduren) bei Hochsprachen fast komplett abgelöst.
Auch PowerShell unterstützt Klassen. Allerdings steht dazu in der Dokumentation recht vielsagend:
Class Definition:
Declares the name of a class, as well as a definition of the variables,
properties, and methods that comprise the class.
Although it is possible to create a class in Windows PowerShell, it's
not a very straightforward process and definitely goes beyond the scope
of this introductory manual. So, für the time being, forget we even
mentioned it.
Auch wenn es syntaktisch geht, scheinen die Entwickler diesen Weg nicht weiter öffnen zu wollen. Gut finde ich es nicht aber wenn man heute also eigene Klassen bauen will, dann wird man eben Visual Studio anwerfen und sich die passenden Klassen als .NET-DLLs oder Commandlets schreiben.
PowerShell und Events
Es gibt noch andere "Events" in PowerShell, welche automatisch Code ausführen können. Die können auf Timer aber auch WMI-Vorgänge triggern. Allerdings sind diese nur solange aktiv, wie die PowerShell-Box auch offen ist. Bislang setzte ich diese nicht ein.
- Chapter 31. Event Handling
Introduction
http://www.pavleck.net/PowerShell-cookbook/ch31.html
PowerShell und Outlook
Siehe dazu Outlook und PowerShell
Exchange Proxy Addresses
Gerade die Anpassung von Proxy-Addresses ist eine häufige Aufgabenstellung für Exchange Administratoren. Auch das gestaltet sich relativ einfach, z.B.:
$mb = get-mailbox fcarius
$mb.EmailAddresses += "smtp:frank.carius@msxfaq.test","fkcarius@msxfaq.test"
$mb | set-mailbox
Wenn es nur eine Adresse ist, kann man das auch direkt auf der PowerShell machen.
Set-Mailbox fcarius -EmailAddresses @{Add="fkarius@msxfaq.test"} Set-Mailbox fcarius -EmailAddresses @{Remove="fkarius@msxfaq.test"}
Selbst in Exchange 2007 und höher schon lange nicht mehr geläufige Adressen wie X.400, MSMail, CC:Mail können so einfach addiert werden
$mb.emailaddresses += "X400:C=DE;.. "
- HOW TO: Add additional email
addresses to a recipient
http://exchangepedia.com/2007/03/how-to-add-additional-email-addresses-to-a-recipient.html
Mehrsprachigkeit
Ich beschränke mich bei Powershell-Skripten in der Regel auf eine direkte Ausgabe von Meldungen auf den Bildschirm über "Write-Host". Wer aber Skripte für verschiedene Länder entwickelt und lokale Meldungen ausgeben will, kann dies mit Powershell ebenfalls tun. Der Trick dabei ist, dass man beim Write-Host einfach einen Platzhalter verwendet, dem in einer Language-Datei die entsprechende Schreibweise zugewiesen wird.
# So könnte in einer Zeile eine Ausgabe aussehen Write-Error $EnableAntimalwareScanning_LocalizedStrings.res_error_engines_not_updated
Sie sehen, dass das eigentlich nur eine "Dollar"-Variable ist. Nun müssen wir diese noch definieren. Das geht einfach über eine Textdatei:
ConvertFrom-StringData @' ###PSLOC res_error_no_permission = Anti-malware scanning is successfully enabled. res_info_done = Finished Job {0} on the server. res_info_update = Updating {0}. Last Updated : {1} ###PSLOC '@
Genau genommen ist das ja ein Powershell-Code, der aus einer Liste von Strings mit einem Wert eine Hashtable macht. für jede Sprache legen Sie einfach so eine Datei ein, bei der sie dann auf der rechten Seite die Übersetzung ablegen. Natürlich müssen die String auf der linken Seite eindeutig sein. Diese Datei wird dann im eigentlichen Programm vor der ersten Ausgabe eingebunden:
Import-LocalizedData ` -BindingVariable EnableAntimalwareScanning_LocalizedStrings ` -FileName Enable-AntimalwareScanning.strings.psd1
Diese Funktion Import-LocalizedData versucht nun zuerst in Unterverzeichnissen, die den Namen der lokalen Sprache, basierend auf dem Wert in $PSUICulture, haben, so eine Datei zu laden. Sollte es diese finden, dann haben wir eine passende Übersetzung. Wenn die Datei nicht geladen werden kann, fällt das Commandlet auf die Datei neben dem Powershell-Skript zurück.
- about_Script_Internationalization
https://technet.microsoft.com/en-us/library/dd315390.aspx - Import-LocalizedData
https://technet.microsoft.com/en-us/library/hh849919.aspx - Windows PowerShell 2.0 String Localization
https://rkeithhill.wordpress.com/2009/10/21/windows-powershell-2-0-string-localization/ - PowerShell 2.0: One Cmdlet at a Time
#106 Import-LocalizedData
http://www.jonathanmedd.net/2010/06/powershell-2-0-one-cmdlet-at-a-time-106-import-localizeddata.html
Microsoft PowerShellPack
Auch Microsoft ist ja nicht ganz inaktiv. Auf http://code.msdn.microsoft.com/PowerShellPack gibt es ein Paket mit zusätzlichen Befehlen, die sie einfach einbinden können. Hier ein Auszug der "FileSystem"-Optionen
PS > Import-Module FileSystem PS > Get-Command -Module FileSystem CommandType Name Definition ----------- ---- ---------- Function Copy-ToZip ... Function Get-DuplicateFile ... Function Get-FreeDiskSpace ... Function Get-SHA1 ... Function Mount-SpecialFolder ... Function New-Zip ... Function Rename-Drive ... Function Resolve-ShortcutFile ... Function Start-FileSystemWatcher ...
Interessant ist hier z.B. die Möglichkeit zu Packen und Entpacken aber auch der "FileSystemWatcher" ist durchaus nicht zu verachten.
Quest PowerShell Tools
Quest ist ja nun eine nicht ganz unbekannte Firma im Bereich Migration, Management, Monitoring etc. für PowerShell Administratoren gibt es zwei sehr interessante Produkte, die zudem kostenfrei sind und ich auch selbst gerne verwende:
- PowerGUI
Diesen leistungsstarken Editor gibt es zwar auch in einer kommerziellen Version, aber die kostenfreie Version ist geradezu prädestiniert für PowerShell Einsteiger und Fortgeschrittene, denen Notepad zu wenig bietet und die Windows ISE ebenfalls nicht weit genug geht. - QAD Cmdlets
Das kommerzielle "ActiveRoles" nutzt im unterbau ebenfalls PowerShell und mit den QAD-Paket stellt Quest kostenfrei ein paar Commandlets zur Verfügung, die den Zugriff auf das AD stark vereinfachen. Sicher kann man auch mit ADSI selbst die Aktionen durchführen oder seit Windows 2008 mit den Active Directory-CMDLets arbeiten, die aber einen ADWS auf dem DC benötigen. Die Quest-Tools sind schnell installiert und rüsten schon viele Jahre fehlende Funktionen für PowerShell nach. Nach der Installation ist das Einbinden ganz einfach.
Add-PSSnapin Quest.Activeroles.ADmanagement
Nicht vergessen darf man natürlich auch das Wiki und die Beispielcodes rund um PowerGUI und natürlich das Blog von Dimitrji Sotnikov, dem Kopf hinter PowerGui und PowerShell MVP.
- Powergui
http://www.quest.com/powergui-freeware/ - Free PowerShell Commands für Active Directory
http://www.quest.com/PowerShell/activeroles-server.aspx - PowerGUI Library
http://www.powergui.org/kbcategory.jspa?categoryID=21 - Quest's QAD Cmdlets
http://blogs.technet.com/b/evand/archive/2007/06/23/quest-s-qad-cmdlets.aspx
Weitere Links
Microsoft Consultant Exchange & Skype for Business (m/w)
Kommen Sie zu Net at Work. Wir haben spannende Projekte bei innovativen Kunden. Unser Team arbeitet kollegial und kooperativ – ständiger Austausch und Weiterbildung sind bei uns Standard.
https://www.netatwork.de/unternehmen/karriere/
-
PowerShell4Admin
PowerShell - Eine Einführung für Administratoren - PSModule
- PSRemote
- WinRM
- PowerShell Klassen
-
Jeffrey Snover: Der Mann der PowerShell quasi "erfunden" hat
http://www.microsoft.com/presspass/exec/de/snover/default.mspx -
PowerShell Blog
http://blogs.msdn.com/b/PowerShell/ -
TechNet Magazin: Remote PowerShell
http://technet.microsoft.com/de-de/magazine/2009.08.windowsPowerShell.aspx -
Laymans' guide to PowerShell 2.0 remoting
http://www.ravichaganti.com/blog/?p=1780 -
Mastering PowerShell eBook'
http://PowerShell.com/Mastering-PowerShell.pdf -
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 -
PowerShell und Visual Studio
Templates für eigene PowerShell Snapins in Visual Studio installieren - http://gsexdev.blogspot.com/2005/11/using-monad-and-wmi-with-exchange-2003.html
- http://dmitrysotnikov.wordpress.com/2007/09/06/wmi-PowerShell-for-exchange-2003/
- PowerShell Tutorial 12 : Part 1: Active Directory Management
http://www.PowerShellpro.com/PowerShell-tutorial-introduction/PowerShell-tutorial-active-directory/ - Mastering PowerShell in your Lunch Break (L>INK NICHT MEHR gültig, Suche
nach einem Spiegel)
Day 1: Getting Organized http://PowerShelllive.com/blogs/lunch/archive/2007/03/26/day-1-getting-organized.aspx
Day 2: Writing Scripts and Translating VBScript
http://PowerShelllive.com/blogs/lunch/archive/2007/03/28/day-2-writing-scripts-and-translating-vbscript.aspx
Day 3: Discovering objects (COM, WMI & ADSI)
http://PowerShelllive.com/blogs/lunch/archive/2007/03/29/day-3-objects-wmi-and-adsi.aspx
Day 4: Ins and Outs of the Windows Registry
http://PowerShelllive.com/blogs/lunch/archive/2007/03/31/day-5-ins-and-outs-of-the-windows-registry.aspx
Day 5: using WMI
http://PowerShelllive.com/blogs/lunch/archive/2007/04/02/day-5-using-wmi.aspx
Day 6: ADSI Connecting to Domains/Computers and Binding to Objects
http://PowerShelllive.com/blogs/lunch/archive/2007/04/04/day-6-adsi-connecting-to-domains-computers-and-binding-to-objects.aspx
Day 7: Manage Users
http://PowerShelllive.com/blogs/lunch/archive/2007/04/05/day-7-manage-Users.aspx -
PowerShell Challenge (Phyton Challenge)
http://thePowerShellguy.com/blogs/posh/archive/tags/PoSH+Challenge/default.aspx - Windows Forms Table
http://gsexdev.blogspot.com/2007/12/mailbox-folder-size-comparison.htm - Amazing But True: Things You Never Dreamt You Could Do With
Windows PowerShell.
https://www.livemeeting.com/cc/mseventsbmo/view?id=1032313506&role=attend&pw=48928A1E - Windows PowerShell Looking Good
http://technet.microsoft.com/en-us/magazine/cc510337.aspx - Windows PowerShell Week Question and Answer Log
http://www.microsoft.com/technet/scriptcenter/webcasts/psweek/day3qanda.mspx - Managing Exchange 2007 Recipients with C#
http://knicksmith.blogspot.com/2007/03/managing-exchange-2007-recipients-with.html - ASP.Net nutzt PowerShell für Anlegen einer Mailbox
http://blogs.msdn.com/akashb/archive/2009/01/30/howto-using-PowerShell-in-asp-net-net-framework-2-0.aspx - Active Directory Administrative Center für Windows Server 2008
R2 implemented using ADPowerShell!
http://blogs.msdn.com/adPowerShell/archive/2009/03/27/active-directory-administrative-center-for-windows-server-2008-r2-implemented-using-adPowerShell.aspx - Active Directory Administrative Center: Getting Started
http://technet.microsoft.com/en-us/library/dd560651.aspx - Packet Sniffer für PowerShell
http://blog.robbiefoust.com/?p=68 - Keith Hill Blog
http://keithhill.spaces.live.com
Umfangreiche Beschreibung zu PowerShell Schritten und im SkyDrive liegen einige interessante Samples - Peter's PowerShell Blog (German only)
http://PowerShellcrashkurs.wordpress.com/ - PowerShell Sniplets
http://itriese.de/category/code-snippets/PowerShell/ - PowerShell : Using Try / Finally block to catch a Ctrl-C and
cleanup
http://sushihangover.blogspot.com/2012/03/powershell-using-try-finally-block-to.html