Peter’s PowerShell Blog (German only)

Mein Kurztrip zur TechEd in Berlin

November 13, 2009 · Kommentar schreiben

JeffreySnoverAtTechEd09 
(Jeffrey Snover während eines kleinen Intermezzos während seines TechEd 09-Vortrags in Berlin)

Ich war dann doch zu mindestens einen Tag auf der TechEd 09 (dem Doktor sei Dank;), so dass ich den (inoffiziellen) „PowerShell-Tag“ miterleben konnte.  Es gab drei Vorträge:

>Remote Management Improvements and Solutions for Windows Server 2008 R2 - der Vortrag von Jeffrey Snover (insgesamt ein guter und wie üblich unterhaltsamer Vortrag, wenngleich er ein wenig zu sehr an der Oberfläche blieb, für die Mehrheit der Teilnehmer aber sicher sehr informativ war – seine Vortragsfolien gibt es hier). Mit dabei war auch ein wenig „PowerShell-Prominenz“ (u.a. Tobias Weltner und Thomas Lee, der die britische PowerShell-User Group mitgründete und, im Stile eines echten UserGroup-Meetings, einen dicken Stapel DVDs mit PowerShell-Tools verteilte).

>Microsoft SQL Server Automation including PowerShell Support (im Konferenzheftchen hieß der Vortrag noch „SQL Server Management with PowerShell“, was aber ein Fehler war. Es ging nur in den etwa letzten 5 Minuten um PowerShell und der Vortrag litt ein „wenig“ unter einer wenig reaktionsfreudigen virtuellen Maschine).

>Managing Windows Server 2008R2 and WIndows 7 with PowerShell V2 von Corey Heins (auch ein interessanter Vortrag mit aktuellem Bezug – wenn der Referent aber nachdem 3/4 des Vortrags vorbei sind das ForEach-Object-Cmdlet erklärt wird deutlich, dass er sich in erster Linie an den PowerShell-Neuling richtete). Trotzdem interessante kleine Beispiele und ein paar Tipps am Rande (etwa zu IPSec als einfacher und sicherer Authentifizierungsmechanismus).

Allen drei Vorträgen war gemeinsam, dass sie sehr an der Oberfläche blieben. Neu ist auch, dass es in aktuellen Vorträgen zur PowerShell weniger um technische Details zur PowerShell geht, sondern in erster Linie um die Rolle der „neuen“ Shell im Rahmen von Windows Server 2008 R2.  Stichwort: TCO (lange nichts mehr davon gehört) senken durch intelligente Administration. Wirklich schade war, dass es bei keinem der Vorträge die Gelegenheit gab Fragen zu stellen – gerade für Jeffrey Snover hätte ich einige Fragen gehabt – so fuhr ich mit gemischten Eindrücken und einigen unbeantworteten Fragen wieder nach Hause. Die Scripting Guys durften leider auch nicht aus Redmond kommen (auch bei Microsoft wird gespart, was sich u.a. auch bei Namen-Badges bemerkbar macht, die neuerdings aus Papier sind und nicht mehr aus Plastik wie früher).

Insgesamt hat die TechEd 09 auf mich (wieder einmal) einen eher gemischten Eindruck hinterlassen. 7.000 Teilnehmer und über 700 Vorträge sprechen für sich. Theoretisch war für jeden etwas dabei, insbesondere natürlich,wenn man sich über die aktuellen Server-Produkte Windows Server 2008 R2, Exchange Server 2010, ForeFront, System Center und diverse andere Server-Produkte von Microsoft informieren wollte. Groß vertreten war Intel als Aussteller (die eigentlich immer dabei sind), mit dabei waren AMD, EMC, IBM und HP.  Leider weiß man bei den Vorträgen nie was einen erwartet. Nicht alle halten, was sie zunächst versprechen. Von den 736 Vorträgen waren nur 47 auf 400er-Niveau (Experten-Level), 288 waren auf 300er-Niveau (Advanced) und 232 auf 200er-Niveau (Intermediate), was einiges über die Gewichtung der Konferenz aussagt.

Die Konferenz fand in der Berliner Messe – Südeingang statt (leider nicht im ICC, wie ich zunächst dachte). Man braucht eine Weile, um sich zu orientieren (wenngleich alles vorbildlich beschildert wurde) und die ganze Messehallen haben den Charme einer typisch deutschen Messehalle aus den 80er Jahren – heute IT, morgen Nutzfahrzeuge (ich kannte die Messe bereits vom Linux-Tag 2008, für den das Ambiente etwa besser passt). Klein Vergleich zum netten Konferenzcenter in Barcelona. Nächstes Jahr soll die TechEd anscheinend wieder in Berlin stattfinden. Berlin ist zwar immer eine Reise wert, aber wenn irgendwie möglich nicht im November (wie wäre es mit Mai?).

→ Einen Kommentar schreibenKategorien: WPSTipps

Wie viele PowerShell-Session gibt es auf der PDC09?

November 11, 2009 · Kommentar schreiben

Ein wenig interessanter als die Frage welche Aussteller es auf einer Konferenz gibt ist natürlich die Frage, welche Vorträge es gibt. Auch das lässt sich herausfinden. Das folgende PowerShell 2.0-Skript stammt von MVP Doug Finke – ich habe es lediglich ein wenig modifiziert. Es benutzt die WPK-Funktionen aus dem neuen PowerShellPack für die PowerShell 2.0, mit dem sich relativ einfach (aber immer noch relativ anspruchsvoll) WPF-Funktionalitäten kapseln und in einem PowerShell-Skript einsetzen lassen.

# Ermöglicht eine Suchabfrage gegen einen RSS-Feed
# in diesem Fall der PDC-Konferenz
if(-Not (Get-Module wpk)) { Import-Module WPK}
$Wc = New-Object System.Net.WebClient
$Feed = [xml] ($Wc.Downloadstring(„
http://microsoftpdc.com/Sessions/RSS“))
$Global:PdcInfo = $Feed.Rss.Channel.item | Sort-Object Title | Foreach-Object {$_}
New-Window -WindowStartupLocation CenterScreen -Width 600 -Height 480 -Show {
    New-Grid -Rows 40, 50*, 100* -Columns 1 {
        New-TextBox -Name Search -Margin 4 -On_PreviewKeyUp {
            $Titles = $this.Parent.Parent | Get-ChildControl Titles
            $Titles.ItemsSource = ($Global:PdcInfo | Where-Object {$_.Title -match $this.Text} )
        }
        New-ListBox -Name Titles -Row 1 -Column 0 -Margin 5 `
            -DisplayMemberPath title  -On_SelectionChanged {
                $Session = $this.Parent.Parent | Get-ChildControl Session
                $Session.Source = $this.SelectedItem.link
        }
        New-WebBrowser -Name Session -Row 2 -Column 0 -Margin 5
    }
}

Ein schönes Beispiel, das zeigt in welche Richtung die PowerShell 2.0 mit Erweiterungen mit dem WPK-Modul geht.

→ Einen Kommentar schreibenKategorien: WPSTipps

Start-Transcript – kleiner Bug, einfaches Workaround

November 6, 2009 · Kommentar schreiben

Das Start-Transcript-Cmdlett besitzt (genau wie Stop-Transcript) einen kleinen Bug, der mit der Version 2.0 nicht behoben wurde. Wird Start-Transcript aufgerufen während bereits eine Aufzeichnung läuft, resultiert ein Fehler, der sich auch mit ErrorAction SilentlyContinue nicht unterdrücken lässt.

Der folgende kleine Workaround behebt die kleine Unschönheitheit, in dem aus dem Fehler über ErrorAction Stop ein terminierender Fehler gemacht wird, der mit Try/Catch (oder dem Trap-Befehl) abgefangen werden kann:

# Set-Transcript-Bug Workaround
try
{
Start-Transcript -ErrorAction Stop
}
catch
{ „Fehler beim Aufruf von Start-Transcript ($($Error[0]))“ }

→ Einen Kommentar schreibenKategorien: WPSTipps

Kleine Tipps für Zwischendurch – wieviele Aussteller gibt es auf der TechEd 2009 in Berlin?

November 5, 2009 · Kommentar schreiben

Nächste Woche findet in Berlin im altehrwürdigen ICC die TechEd 2009 Europe (das erste Mal seit vielen Jahren wieder in Deutschland) statt, mit dabei unter anderem ein Vortrag von „PowerShell-Erfinder “ Jeffrey Snover zum Thema „Remote Management Improvements and Solutions for Windows 2008 R2″  (in dem es aber vermutlich nur um den üblichen Überblick gehen wird, wenngleich der Vortrag Sicherheit einen Besuch wert ist – ob ich dabei werde ist noch nicht sicher, auch wenn PowerShell-Vorträge zu besuchen eine Art Hobby von mir ist).

Mich hat vor allem die Frage interessiert, wie viele Aussteller vertreten sind und aus welchen Ländern sie stammen.

Mit der PowerShell und einem einfachen regulären Ausdruck lässt sich die Frage (relativ) schnell beantworten:

1) Ausgangspunkt ist die TechEd-Webseite http://www.msteched.com/europe/Public/exhibitors.aspx.

2) Leider ist es mir nicht gelungen, den Webseiteninhalt über ein (New-Object System.Net.WebClient(TechedUrl, „TechEdUrls.txt“) zu laden, da die Austellerdaten aus einer XML-Datei per JavaScript nachgeladen werden – ich musste daher einen kleinen Umweg gehen und den Webseiteninhalt aus dem Browser in eine Textdatei kopieren.

$DownloadDatei = (gl).Path+“\TechEdUrls.txt“
Write-Host „$AnzahlUrls Austeller-URL’s gefunden“

Hat man die Daten, kann man ein wenig „Data Mining“ betreiben;

Write-Host „VMWare ist dabei: $((Get-Content $DownloadDatei)-Match „vmware“)“

Oder die URLs der Aussteller nach ihrer Top-Level-Domain gruppieren:

$TopLevelDoms = Select-String -Path $DownloadDatei -Pattern „http://www\.([a-z-0-9]+\.)*(?<Top>\w{2,3})“
$TopLevelDoms | Group-Object -Property { $_.Matches[0].Groups["Top"].Value} | Sort-Object Count -Descending

Dabei stellt sich z.B. heraus, dass von den insgesamt 98 Ausstellern nur zwei eine de-Domäne besitzen (2x at), die Schweiz  scheinbar nicht vertreten ist, und es mit 89 com-Domains einen eindeutigen Schwerpunkt gibt (was mich nicht gerade zuversichtlich bezüglich des „Zustands“ der hiesigen Software-Industrie stimmt bzw. ein Beleg dafür ist/sein könnte, dass das Microsoft-Windows-Ökosystem nach wie vor eindeutig seinen Schwerpunkt in den USA hat).

Ab jetzt wird es ein wenig besser, denn über die URL http://www.msteched.com/resources/Content_Files/EU_exhibitor.xml lässt sich die Ausstellerliste auch direkt laden.

Wie wäre es mit einem:

$XDoc = new-object System.Xml.XmlDocument
$XDoc.Load(„
http://www.msteched.com/resources/Content_Files/EU_exhibitor.xml„)
$XDoc.Exhibitors.Exhibitor.Count

oder

$XDoc.Exhibitors.Exhibitor | Select Website

oder

$XDoc.Exhibitors.Exhibitor | Where { $_.WebSite -like „*de“}

100% aussagekräftig ist diese Statistik natürlich nicht, denn mind. ein deutscher Aussteller besitzt eine com-Domäne und eine der de-Domänen gehört einem bekannten Software-Hersteller aus Russland.

Aber das kleine Beispielchen sollte in erster Linie ein weiteres Mal zeigen, wie nett und flexibel die PowerShell sein kann.

PS: Mit der PowerShell 2.0 kam bei Select-String der -AllMatches-Parameter hinzu, durch den alle Übereinstimmungen in einer Zeile gefunden werden (bislang wurde nur die erste Übereinstimmung gefunden).

→ Einen Kommentar schreibenKategorien: WPSTipps

Die PowerShell um Befehlskonstrukte erweitern

Oktober 27, 2009 · 1 Kommentar

Die PowerShell ist wirklich sehr flexibel erweiterbar. Dank der Möglichkeit, einem Funktionsparameter einen Befehsblock übergeben zu können, auch um Befehlskontrukte. Ein Kleinigkeit, die mich schon öfter gestört hat ist der Umstand, dass es ein wenig umständlich ist eine Aktion auszuführen, wenn ein Pipeline-Objekt einen Where-Filter nicht erfüllt. Ich hätte gerne eine Art Where { Filter } { True-Part } { False-Part}-Konstrukt. Was bei VBScript&Co gänzlich undenkbar ist, ist bei der PowerShell keine allzu große Herausforderung:

function IfElse-Object
{
  param
  (
    [Parameter(Mandatory=$true,
               ValueFromPipeline=$true)]
    [Object[]]$InputObject,
    [Parameter(Position=0, Mandatory=$true)]
    [ScriptBlock]$Cond,
    [Parameter(Position=1, Mandatory=$true)]
    [ScriptBlock]$TruePart,
    [Parameter(Position=2, Mandatory=$true)]
    [ScriptBlock]$FalsePart
  )
  process
  {
   if (&$Cond)
   { &$TruePart }
   else { &$FalsePart }
  }
}

Während der InputObject-Parameter seinen Inhalt aus der Pipeline holt, erhalten die Parameter Cond, TruePart und FalsePart ihren Inhalt über die Werte, die beim Aufruf übergeben werden.

Als nächstes wird ein Alias definiert:

Set-Alias -Name IfElse -Value IfElse-Object

Aufgerufen wird der neue „Befehl“ wie folgt:

Get-Item -path *.* | IfElse { $_.Length -eq 0 } { „$($_.Name) ist leer“}  { „$($_.Name) ist nicht leer“ }

Ohne die neue Befehlskonstruktion wird es gleich ein wenig komplizierter, sofern man nicht auf die Standard-Lösung mit Foreach und einem „braven“ If-Befehl zurückgreifen möchte:

Get-Childitem -path *.* | &{ process { $Datei=$_.Name;switch ($_.Length) {{ $_ -eq 0} { „Datei $Datei ist leer“} { $_ -ne 0} { „Datei $Datei ist nicht leer“}}}}

→ 1 KommentarKategorien: WPSTipps

PowerShell 2.0 ist offiziell

Oktober 27, 2009 · Kommentar schreiben

Im PowerShell Team Blog war es bereits zu lesen: Im Rahmen des Windows Mangement Framework 2.0 steht die PowerShell 2.0 nun auch ganz offiziell für Windows XP, Windows Server 2003 und Windows Server 2008 zur Verfügung. Allerdings nicht im Download-Center (hier gibt es nach wie vor CTP2 und CTP3), sondern auf einer eigenen Support-Seite:

http://support.microsoft.com/kb/968929

PS: Jetzt wird es wohl langsam Zeit, dass mein Buch fertig wird.

→ Einen Kommentar schreibenKategorien: WPSTipps

Neu: Das PowerShell Pack mit einer wahren Fülle an Funktionen

Oktober 16, 2009 · Kommentar schreiben

Im PowerShell Team Blog war die Meldung heute bereits zu lesen, daher an dieser Stelle nur die Kurzfassung: Das PowerShell-Team bei Microsoft hat unter dem offiziellen Namen Windows 7 Ressource Kit PowerShell Pack ein „Add-On“ (die Bezeichnung ist anhand der Fülle an Funktionen eine leichte Untertreibung) freigegeben, dass die PowerShell 2.0 vermutlich um alle das erweitert, was man immer schon vermisst haben dürfte (wie wäre es mit einer Test-64Bit-Funktion;). Die Namensgebung ist eventuell ein wenig irritierend. Das PowerPack ist nicht an Windows 7 gebunden, der Titel bezieht sich nur auf das Buch „Windows 7 Ressource Kit“, das kürzlich bei Ms Press erschienen ist, und dem das PowerPack beiliegt.

Der Form halber auch der Download-Link: http://code.msdn.microsoft.com/PowerShellPack

→ Einen Kommentar schreibenKategorien: WPSTipps

Ein Get-Object-Pendant für die PowerShell

September 28, 2009 · Kommentar schreiben

Interessant, was alles so möglich ist, wenn man weiß wie es geht. In VBScript gibt es die GetObject-Funktion, die man bei der PowerShell nicht wirklich braucht. Sollte man sie aber doch aus irgendeinem Grund benötigen, lässt sie sich durch eine kleine Anleihe aus der .NET-Klassenbibliothek und einem indirekten Aufruf per Invoke-Member nachbauen.

Das folgende Beispiel ruft per „Get-Object-Emulation“ die SetPassword-Methode auf mit der sich das Passwort eines lokalen Benutzers setzen lässt:

# Nachbildung der GetObject-Funktion
$UserName = „Susi“
$PwNeu = „geheim“
[System.Reflection.Assembly]::LoadWithPartialName(„Microsoft.VisualBasic“) | Out-Null
$User = [Microsoft.VisualBasic.Interaction]::GetObject(„WinNT://./$UserName,user“,$Null)
$Im = [System.Reflection.Bindingflags]::InvokeMethod
$GmType = $User.GetType()
$GmType.InvokeMember(„SetPassword“, $Im, $Null, $User, $PwNeu)
$GmType.InvokeMember(„SetInfo“,$Im, $Null, $User, $Null)
Write-Host -fore green „Auftrag ausgeführt…“

Diese Techniken haben mit der PowerShell nur indirekt etwas zu tun. Sie basieren darauf, dass die durch das .NET Framework zur Verfügung gestellte „Infrastruktur“ ebenfalls über Klassen der .NET-Klassenbibliothek ansprechbar ist. Wer die obige Befehlsfolge nicht auf Anhieb versteht sollte sich daraus nichts machen. Das ist eher etwa für die „Insider“ – allerdings ist alles in der .NET-Referenz ausführlich dokumentiert. Das ist ein angenehmer Kontrast zu früher, wo man sich ein solches Insider-Know how nur durch gute Kontakte zum Hersteller oder harte Arbeit erwerben konnte.

→ Einen Kommentar schreibenKategorien: WPSTipps

COM-ErrorCode abfragen

September 28, 2009 · Kommentar schreiben

Wer häufiger mit COM-Objekten arbeitet, möchte hin und wieder den ErrorCode abfragen, den ein solches COM-Objekt immer dann liefert, wenn die Operation aus irgendeinem Grund fehlschlägt. Wie es aussieht, ist es gar nicht so einfach an diesen ErrorCode heranzukommen. Hier erst einmal ein einfaches Beispiel:

$GPMT = new-object -com GPMGMT.GPM
$GPMT.GetDomain(„GibtEsNicht.de“, $Null, 1)

Zuerst wird die Gruppenrichtlinien-Komponente GPMGMT.GPM instanziert, anschließend wird eine Domäne angesprochen, die es nicht gibt. Das Ergebnis ist eine COM-Exception, deren ErrorCode (HResult) 0×8007054B lautet. Die Frage ist, wie sich dieser Errorcode abfragen lässt. Theoretisch über das Exception-Objekt, doch wie ein

$Error[0].Exception.GetType().Name

verrät, ist es eine MethodInvocationException und keine COMException. Diese wird erst über die GetBaseException-Methode geliefert:

$Error[0].Exception.GetBaseException().Errorcode

-2147023541

Und wie macht man noch einmal aus einer Integer-Zahl eine Hexadezimalzahl? Zum Beispiel über ein

[Convert]::ToString($ErrorCode,16)

oder

„{0:x}“ -f $ErrorCode

Ein Trap-Befehl, der diese Ausnahme abfängt und den Fehlercode ausgibt könnte wie folgt aussehen:

trap [System.Management.Automation.MethodInvocationException] { $ErrorCode = ($_.Exception.GetBaseException()).ErrorCode; „Errorcode: {0:x}“ -f $ErrorCode;Continue}
$GPMT = new-object -com GPMGMT.GPM
$GPMT.GetDomain(„GibtEsNicht.de“, $Null, 1)

Aus Gründen, die ich im Moment leider nicht im Detail nachvollziehen kann, lässt sich mit dem Trap-Befehl nicht direkt auf die System.Runtime.InteropServices.COMException prüfen. Außerdem muss die inner Exception über GetBaseException() und nicht über InnerException abgefragt werden

Das sind Details, die ich gerne Mal bei Gelegenheit von einem COM-Experten erklären lasse. Für den Moment gilt die Devise, dass wenn es funktioniert, wann nicht immer über die genauen Gründe philosophieren sollte.

→ Einen Kommentar schreibenKategorien: WPSTipps

Kleine Tipps für Zwischendurch – Alle ProgIds auflisten und ein PowerShell-Skript von VBScript aus aufrufen

September 17, 2009 · Kommentar schreiben

Dieser Tipp ist (wie viele andere natürlich auch) etwas älter, aber sehr nützlich. Möchte man wissen, ob eine bestimmte „ProgID“ (für das Ansprechen einer COM-Komponente) existiert oder wie eine ProgID für eine Anwendung/Komponente, deren Namen man kennt, lauten könnte, ist der folgende Befehl Gold wert, denn er listet alle ProgIDs auf:

dir REGISTRY::HKEY_CLASSES_ROOT\CLSID -include PROGID -recurse | foreach {$_.GetValue(„“)}

Dass es für die PowerShell offenbar keine ProgID gibt (und sie daher nicht per COM-Automatisierung gesteuert werden kann) macht der folgende Befehl deutlich:

dir  REGISTRY::HKEY_CLASSES_ROOT\CLSID -include PROGID -recurse | foreach { $Progid = $_.GetValue(„“); if ($Progid -match „Shell“) { $Progid } } | sort-object

Es werden zwar etliche ProgIDs aufgelistet, der Name „PowerShell“ ist nicht dabei.

Wie sich die ProgID zu einer Exe-Datei (sofern vorhanden) finden lässt, verrät der folgende „Tipp“, bei dem es sich ein PowerShell-Skript handelt, bei dem was die .NET-Funktionalität angeht, die im dem Skript angesprochen wird, an das sprichwörtlich „Eingemachte“ geht:

http://www.eggheadcafe.com/conversation.aspx?messageid=30740363&threadid=30740360

Irgendwie habe ich das Gefühl, es müsste eine einfachere Lösung geben:)

Ausgangspunkt für die Suche war die Frage gewesen, wie sich ein PowerShell-Skript von einem VBScript-Skript aus aufrufen lässt (damit ließe sich ein PowerShell-Skript z.B. als Anmeldeskript im Rahmen der Gruppenrichtlinien ausführen). Wie es aussieht, gibt es mind. 2 Lösungen:

1) Der Aufruf von PowerShell.exe über das WshShell-Objekt und seine Run-Methode. Die folgende Befehlsfolge führt das PowerShell-Skript C:\PS\Test.ps1 aus:

‘ Ruft ein PowerShell-Skript auf
Option Explicit
Dim WShell, PsCmd
Set WShell = CreateObject(„Wscript.Shell“)
‘ PsCmd = „powershell.exe -noprofile -noexit -Command &’C:\PS\Test.ps1′“
PsCmd = „powershell.exe -noprofile -Command &’C:\PS\Test.ps1′“
WShell.Run PsCmd

Die Variante mit dem -NoExit-Parameter bewirkt, dass das PowerShell-Konsolenfenster nicht wieder geschlossen wird.

2) Eine COM-Komponente mit dem Namen ActiveXPosh, die von der Firma Sapien dankenswerterweise free“ (ganz ohne E-Mail-Registrierung geht es allerdings nicht) zur Verfügung gestellt wird. Der Eval-Methode der Komponenten wird ein beliebiger PowerShell-Befehl übergeben. Weitere Infos gibt es hier. Der Downloadlink ist http://www.primaltools.com/downloads/communitytools/.

→ Einen Kommentar schreibenKategorien: WPSTipps