DSC Pullserver mit SQL Server als Datenbank

Ein DSC Pullserver verwendet standardmäßig eine ESENT DB-Datenbank (das „ESE“ steht für Extensible Storage Engine) für das Abspeichern der Konfigurationszustände der einzelnen Nodes. Bei der Umsetzung von DSC wollten es die Entwickler offenbar einfach halten und haben auf eine bewährte Datenbankengine gesetzt, die u.a. von Active Directory und Exchange Server verwendet wird, und die seit Windows XP einfach da ist. Für die Praxis ist eine SQL Server-Datenbank die bessere Option. In erster Linie weil sich dadurch Reporting-Möglichkeiten ergeben, die ansonsten nicht oder nur eingeschränkt zur Verfügung stehen.

Tipp: Ein praktisches kleines Tool für das Betrachten von ESENT DB-Datenbanken ist die ESENT Workbench: https://bitbucket.org/orthoprog/esentworkbench/wiki/Home.

Tipp<: Auf GitHub gibt es einen Managed Essent DB-Provider. Mit seiner Hilfe soll der Zugriff auf eine Datenbank in Managed Code und damit auch per PowerShell sehr einfach einfach: https://github.com/Microsoft/ManagedEsent.

Leider lässt sich eine SQL Server-Datenbank in der aktuellen DSC-Version (Stand: Mai 2018) noch nicht einbinden. Der Grund ist eher trivial. DSC verwendet für den Zugriff auf die ESENT DB-Datenbank benannte Parameter, der für den SQL Server-Zugriff zu verwendende Datenbankprovider versteht diese offenbar nicht und erwartet, dass jeder Parameter durch ein ? repräsentiert wird. Das kann wiederum nur die Jet-Engine von Microsoft Access. Deswegen muss eine Access-Datenbank in Gestalt einer Mdb-Datenbankdatei, die lediglich verknüpfte Tabellen auf die SQL Server-Datenbank enthält, als Vermittler eingeschaltet werden.

Microsoft-Mitarbeiter und PowerShell-Experte Raimund Andrée beschreibt die Hintergründe in einem Blog vom Mai 2017 sehr ausführlich, so dass ich auf seinen Blog verweise, da der alle Fragen beantworten sollte:

https://blogs.technet.microsoft.com/fieldcoding/2017/05/11/using-sql-server-2016-for-a-dsc-pull-server/

Die Vorgehensweise ist, die ESENT-Datenbank Devices.edb durch eine per Microsoft Access erstellte Datenbank mit dem Namen Devices.mdb auszutauschen, deren Tabellen auf die gleichnamigen Tabellen der SQL Server-Datenbank verlinken. Klingt vielleicht umständlich, ist in der Umsetzung aber relativ einfach. Ob es tatsächlich funktioniert ist aber noch ein anderes Thema (Stand 31/05/18 ist es mir nicht gelungen, einen Pull Server mit SQL Server-Datenbanb zu betreiben – die Gründen haber nur indirekt etwas mit DSC zu tun, sondern eher mit der TLS/SSL-Problematik).

Mit Windows Server 2019 soll das Einbeziehen einer SQL Server-Datenbank dann direkt möglich sein:

https://blogs.msdn.microsoft.com/powershell/2018/04/19/windows-pull-server-planning-update-april-2018/
Ob es dieses Update auch für ältere Windows Server-Versionen geben wird ist nicht klar (meine Frage diesbezüglich wurde noch nicht beantwortet)

Ergänzungen aus der Praxis

Das Anlegen einer ODBC-Datenquelle ist aus verschiedenen Gründen nicht ganz so einfach wie es sich in de Anleitung anhört.

>SSL 3.0 kann ein Thema sein. Sollte das Herstellen einer Verbindung hartnäckig an einem Error 18 scheitern, kann das Aktivieren von SSL 3.0 die Lösung sein. Eine praktisches kleines Tool ist IISCrypto.exe (Download unter https://www.nartac.com/Products/IISCrypto/), mit dem sich TLS und SSL sehr einfach aktivieren oder deaktivieren lassen (anschließend ist ein Neustart erforderlich).

Eine Alternative ist der Weg über die lokalen Sicherheitsrichtlinien bzw. Gruppenrichtlinien:

https://dba.stackexchange.com/questions/93127/sql-server-service-won-t-start-after-disabling-tls-1-0-and-ssl-3-0

Man braucht wieder einmal viel Zeit und vor allem Geduld und sehr viel Nachsicht den verantwortlichen DSC-Entwicklern gegenüber.

Kleine Tipps für Zwischendurch: C#-Code testen

Wer lediglich ein paar Zeilen C#-Code testen möchte, muss dafür nicht Visual Studio starten, um dort ein Projekt anlegen zu müssen, wenngleich dies natürlich kein allzu großer Aufwand ist und es mit Visual Studio Code einen Editor gibt, der vielsprachig ist. Es geht auch per PowerShell und dem vielseitigen Add-Type-Cmdlet. Über den MemberDefinition-Parameter wird der C#-Code für eine Membermethode übergeben. Name der Klasse und eventuell auch ein Namespace werden per Parameter festgelegt.

Das folgende Beispiel veranschauhlicht die einfache Vorgehensweise. Eventuell wäre eine statische Methode noch etwas kürzer.

Es gibt sie auch – kommerzielle Tools für die PowerShell

Es gibt nicht viele kommerzielle Tools für die PowerShell, das Angebot ist mehr als überschaubar. Mehr oder weniger spontan fallen mir folgende Produkte ein:

  1. PowerShell Studio von Sapien Technologies
  2. PowerShell Server und die NetCmdlets von n/Software
  3. ScriptRunner von AppSphere
  4. ISE Steroids natürlich von Tobias Weltner
  5. BlueParq von BlueParq BV aus den Niederlande (die Jungs haben diesen Sommer viel Zeit zum Skripten)

Auf BlueParq bin ich erst vor kurzem in einem Artikel in IT-Administrator aufmerksam geworden. Es klingt sehr interessant und ich werde das Tool in Kürze (sprich in den nächsten 3-6 Monaten;) in meinem Blog vorstellen.

Auf zwei weitere kommerzielle Tools bin ich eher per Zufall aufmerksam geworden.

  1. PowerShell Pro Tools
  2. PowerShell Universal Dashboard

Beide Tools stammen von IronMan Software. Insbesondere das Universal Dashboard macht einen sehr interessanten Eindruck, da ich mit seiner Hilfe beliebige „Informationscockpits“ á la Nagios zusammenbauen lassen. Eine naheliegende Anwendung ist es, Daten aus dem Office 365-Portal, etwa Nutzerstatistiken (sofern solche dank DSGVO überhaupt noch erfasst werden dürfen), darzustellen.

Beide Tools werde ich in den nächsten Wochen (hoffentlich werden es keine Monate) an dieser Stelle vorstellen. Wer solange nicht warten möchte, probiert sie am besten selber aus.

Kleine PowerShell-Challenge – CSV-Daten ohne leere Spalten ausgeben

Ich liebe kleine „Programmier-Challenges“, da sie eine Gelegenheit bieten das eigene, in der Regel mühsam erworbene, Wissen anzuwenden. Und da ich mich nach wie vor relativ viel mit der PowerShell beschäftige liegt es nahe, eine solche Herausforderung mit der PowerShell zu meistern. Eine Art Jogging fürs Gehirn. Die PowerShell ist aber nur Mittel zum Zweck. Ob die Challenge mit PowerShell, Python oder einer anderen Programmiersprache spielt dabei keine Rolle.

Die heutige Herausforderung ist einfach formuliert: Gesucht ist eine Technik, durch die beim Konvertieren von CSV-Daten in Objekte nur Spalten berücksichtigt werden, in denen mindestens ein Wert enthalten ist. Leere Spalten sollen nicht ausgegeben werden.

Klingt zunächst einfach. Die Umsetzung ist es auch, sofern man weiß, dass jedes PowerShell-Objekt eine Eigenschaft mit dem Namen Psobject besitzt. Allerdings kann man sich auch schnell in eine Sackgasse manöverieren.

Ausgangspunkt sind CSV-Daten, die in der Variablen $CSVDaten enthalten sind.

Im Mittelpunkt steht die unscheinbare Eigenschaft PsObject, die es bei jedem Objekt gibt. Sie liefert Informationen über die Beschaffenheit des Objekts. Dazu gehört die Properties-Eigenschaft. Sie liefert nicht nur die Namen aller Eigenschaften, sondern über die Value-Eigenschaft auch deren Werte.

Die folgende Befehlsfolge gibt die Namen der Eigenschaften aus bei den Objekten aus, die aus CSV-Konvertierung resultieren.

Das kann Get-Member doch auch, allerdings erhält man hier lediglich die Members, nicht die einzelnen Werte.

Die folgende Befehlsfolge gibt zunächst nur die Namen der Eigenschaften aus, die bei allen aus der CSV-Konvertierung resultierenden Objekten mindestens einen Wert besitzen.

Die Gruppierung ist erforderlich, da die Namen der Eigenschaften pro Objekt ja mehrfach ausgegeben werden. Der Name soll aber nur einmal zurückgegeben werden.

Für den nächsten Schritt werden die Namen einer Variablen zugewiesen.

Jetzt sind alle Properties bekannt, die einen Wert besitzen. Doch wie werden diese Namen verwendet? Ganz einfach: Per Select-Object.

Jetzt soll alles noch in eine Form gegossen werden, die eine Wiederverwenbarkeit vereinfacht. Es wird eine Function definiert. Im Folgenden Beispiel heißt die Function ConvertFrom-CSVData. Das ist in diesem Fall vertretbar, da die Function nur wenige Parameter besitzt, die sich daher mit wenig Aufwand hinzufügen und an die „wahre“ ConvertFrom-CSVData-Function weiterrerichen lassen. In der Praxis wäre eine Proxy-Function die flexiblere Lösung.

Wichtig ist zu wissen, dass wenn eine Function denselben Namen besitzt wie ein Cmdlet, die Function aufgerufen wird und nicht das Cmdlet. Soll die Function ausgeführt werden, muss der Modulname mit einem Backslash am Ende vorangestellt werden.

Hier ist die komplette Function:

Damit wird eine Konvertierung jetzt sehr einfach:

Lohnt sich der ganze Aufwand? Wie immer lässt sich die Frage nicht eindeutig beantworten. Ja, weil es wie Eingangs erwähnt ein gutes „Gehirn-Jogging“ ist. Wer selber zu einem Ergebnis gekommen ist, wird mit Sicherheit stolz auf sich sein und das Gefühl haben die PowerShell besser zu beherrschen. Nein, weil es natürlich im IT-Umfeld Wichtigeres gibt. Auf der anderen Seite: Ich erlebe es immer wieder, dass es in den IT-Abteilungen von Firmen und Behörden immer nur 1-2 „PowerShell-Gurus“ gibt. Wenn überhaupt. In den IT-Abteilungen in Deutschland fehlt es eindeutig an PowerShell-Know how.

Zum Schluß soll das Ganze auch in der Praxis ausprobiert werden.

Ausgangspunkt it etwas CSV-Text:

Der folgende Befehl gibt nur Spalten aus, in denen mindestens ein Wert enthalten ist. Die Spalten EAD1 und EAD3 werden also nicht ausgegeben.

Praktische Neuerung für DSC – das DSCLCM-Modul

Die Konfiguration des LCM ist in der aktuellen DSC-Version etwas umständlich. Zum einen muss man jede Einstellungsänderung in einer Konfiguration zusammenfassen, was grundsätzlich machbar ist, etwas lästiger ist es, dass beim Ändern einer partiellen Konfiguration, etwa dem Hinzufügen einer weiteren Konfiguration, auch alle anderen partiellen Konfigurationen neu gesetzt werden müssen.

Einfacher soll es mit einem neuen Modul mit dem Namen DSCLCM geben, das von den Scripting Guys (es gibt sie also noch;) vor kurzem vorgestellt wurde:

https://blogs.technet.microsoft.com/heyscriptingguy/2018/03/30/introducing-the-dsclcm-utility-for-powershell/

Ich habe das Modul noch nicht getestet, werde es aber in Kürze nachholen.

Kleine Tipps für Zwischendurch: Regexe mit Umlauten und anderen Zeichen und die Fehlermeldung „[x-y]-Bereich in umgekehrter Reihenfolge“

Regexe praktisch und alles andere als kompliziert, wenn man sich auf einfache Anwendungsfälle beschränkt. Etwa, das Zerlegen von Zeilen, die aus einem Tag in spitzen Klammern und einem Rest bestehen. Zum Beispiel:

Der Regex soll „slide“ und den Text liefern, der auf die schließende spitze Klammer folgt. Grundsätzlich kein allzu großes Problem, allerdings liefert der folgende Regex die Fehlermeldung [x-y]-Bereich in umgekehrter Reihenfolge:

Die Erklärung ist ebenfalls ganz einfach (vor allem, wenn man es weiß;). Da ich neben vielen Sonderzeichen auch den Bindestrich prüfe, kommt dieser in der Gruppe ebenfalls vor. Er muss dabei aber am Anfang der Gruppe stehen, da er ansonsten als Metazeichen interpretiert wird. Ich hatte ja erwähnt, dass die Fehlermeldung eine ganz einfache Ursache hat.

Der richtige Regex ist daher:

PoshConf Europe 2018 – es gibt noch freie Plätze und wer speakt wie oft und über was

In knapp 3 Wochen startet in Hannover die PowerShell Conference Europe 2018 – vom 17. bis 20. April. Aktuell gibt es noch freie Plätze. Wer sich immer schon einmal mit dem Erfinder der PowerShell Jeffrey Snover oder dem „Brain“ hinter der PowerShell-Sprache Bruce Payette unterhalten möchte (oder falls vom Gespräch auf der letzten Konferenz noch Fragen offen geblieben sind) hat dazu die Gelegenheit. Alle Infos unter http://www.psconf.eu/.

Ich werde dieses Mal nicht dabei sein, aber mich interessiert natürlich trotzdem wer welche Vorträge hält.

Unter http://powershell.beer steht die gesamte Agenda im JSON-Format zur Verfügung.

Der folgende Befehl gibt sie übersichtlich aus:

(Das $ sollte eigentlich nicht erforderlich sein)

Mich interesiert natürlich welche Sprecher die meisten Vorträge halten und natürlich auch welche das sind. Das kleine „Problem“ ist, dass es bei einigen Vorträgen mehrere Sprecher gibt und die Speaker-Eigenschaft daher auch mehrere Namen enthält.

Der folgende Befehl gibt die Sprecher gruppiert nach ihrem Namen und sortiert nach der Anzahl ihrer Vorträge aus.

Das Problem mit dieser Ausgabe ist nur, dass die Sprecher nicht einzeln aufgelistet werden, da es zu einem Vortrag auch mehrere Sprecher geben kann. Die Speaker-Eigenschaft enthält dann mehrere (zwei oder drei) per Komma getrennte Namen.

Wer das Problem selber lösen möchte, sollte jetzt nicht weiterlesen, sondern sich ca. 1 Stunde Zeit nehmen. Es hat mich nicht ganz so viel Zeit gekostet, aber es war schon ein wenig Hin- und Herprobieren erforderlich bis endlich das gewünschte Ergebnis herauskam.

Der Knackpunkt an der Geschichte war, dass ich zuerst auf Invoke-WebRequest umschalten musste, um den JSON-Text direkt zu erhalten (eventuell ist das auch nicht erforderlich) und dann darauf kommen musste, dass die Rückgabe aus einem einzelnen Objekt-Array besteht und nicht aus vielen Objekten – was die Ausgabe suggeriert (darauf bin ich in den letzten Jahren schon einige Male hereingefallen;) – der entscheidende Test ist für mich immer. ob Measure-Object ein Objekt zurückgibt oder mehrere. Ausgehend von einem einzigen Objekt habe ich dessen Content-Eigenschaft expandiert und aus dem resultierenden JSON-Text Objekte gemacht, die per ForEach durchlaufen werden. Da sich hinter der Speaker-Eigenschaft mehrere Namen verbergen können, werden diese per -split-Operator alle einzeln fein säuberlich getrennt und mit der zuvor gespeicherten Title-Eigenschaft zu einem neuen Objekt kombiniert. Dieses besitzt erneut eine Speaker-Eigenschaft mit dem Namen eines Speakers, nach der gruppiert werden kann.

Alles klar? Egal, hier ist ein möglicher Versuch:

Wer ist der Top-Speaker auf der PowerShell Conference Europe 2018?

Netzwerktools und ihre PowerShell-Pendants

Beim Vorbereiten auf einen MOC-Kurs zu Windows 10 ging es auch um die Netzwerkkonfiguration. Es ist erfreulich, dass in den aktuelleren MOC-Unterlagen auch die PowerShell inzwischen erwähnt wird und Gegenstand einiger Demos und Labs ist.

Da auch für mich als PowerShell-Kenner nicht immer auf Anhieb einfällt was z.B. das Pendant zu Nslookup oder ipconfig /flushdns ist, bin ich froh den folgenden Blog-Eintrag gefunden zu haben, in dem der Autor die klassischen Netzwerkkommandos den PowerShell-Befehlen gegenüberstellt:

https://blogs.technet.microsoft.com/josebda/2015/04/18/windows-powershell-equivalents-for-common-networking-commands-ipconfig-ping-nslookup/

Ein wenig kurios ist allerdings, dass dem Autor nicht klar war, dass PowerShell 5.0 zu verwenden nicht automatisch bedeutet, dass Befehle wie Get-NetIPAddress zur Verfügung stehen, da diese Teil des Betriebssystems und nicht der PowerShell sind. Das Ergebnis waren daher auch ein paar „bei mir läuft es nicht, obwohl ich Version 5.0 verwende“-Kommentare.

Was ich noch suche ist ein Pendant zu dem sehr praktischen Portqry.exe, das aber zuerst von einer Microsoft-Seite heruntergeladen werden muss.

Kleine Tipps für Zwischendurch: Alle Dienstnamen pro Svchost-Prozess ausgeben

Vor kurzem habe ich in einem Blog-Eintrag eine PowerShell-Befehlsfolge gefunden, die zu jedem Svchost-Prozess die Namen der Dienste ausgibt, die von diesem Prozess ausgeführt werden. Die Lösung war gut, aber leider sehr umständlich. Vermutlich war der Autor Entwickler und hat ein wenig zu sehr die Entwicklerdenkweise bei der Umsetzung der eigentlich einfachen Aufgabenstellung angewendet. Bei mir hat es auch ein paar Jahre gedauert bis ich mir diese Denkweise bei der PowerShell abgewöhnt hatte.

Mein Vorschlag für eine Unmsetzung sieht wie folgt aus.

Es kann lediglich eine Weile dauern bis eine Ausgabe erscheint.