Zugriff aus Powershell via WMI auf System Center Configuration Manager
Donnerstag, 9. September 2010, 09:19
Abgelegt unter: Anleitungen | Tags: , , ,

Während den letzten Tagen habe ich mich etwas intensiver mit der Powershell 2.0 befasst und ich habe mich gefragt, ob und wie ich bestimmte Daten mit Hilfe eines Powershell-Skriptes aus SCCM auslesen kann. So habe ich mir vorgenommen, ein Skript zu schreiben, das mir eine Liste aller vorhanden Clients ausgibt und dabei die Info aus SCCM mitliefert, welcher Benutzer letztmals an diesem Client angemeldet war und wann die letzte Kommunikation des Agent mit dem SCCM-Site Server erfolgte.

Konkret interessierte ich mich also für folgende drei Feldwerte aus den Eigenschaften eines Computerobjektes:

  • Name
  • Last Logon User Name
  • Agent Time (neuester Eintrag)

Der erste Teil des Skriptes war einfacher zu realisieren, als ich dies zuerst vermutete:

$query = New-Object System.Management.ObjectQuery
$query.QueryString = "Select * from SMS_R_System order by Name" $searcher = New-Object`
System.Management.ManagementObjectSearcher($query)
$searcher.Scope.Path = "\\<siteserver>\root\sms\site_<sitecode>"
$result=$searcher.Get()

Ich verwende also die ObjectQuery-Klasse aus dem .NET-Framework, setze die entsprechende Query (die natürlich die gewünschten Felder zielgerichteter auslesen könnte, als mit dem simplen „Select *“), und benutze dann die ManagementObjectSearcher-Klasse, um die Abfrage der gewünschten Informationen basierend auf der definierten Query durchzuführen. Hierzu muss natürlich noch definiert werden, wo genau die Daten gelesen werden sollen, wozu in der vierten Zeile <siteserver> durch den Namen des entsprechenden SCCM-Siteservers und <sitecode> durch den dazu passenden Sitecode zu ersetzen ist. Nun noch die Suche gestartet, und schon stehen die gewünschten Daten in $result.

Bis ich nun die Daten als passend formatierte Tabelle in der Powershell lesen konnte, musste ich deutlich länger suchen (und einem Kollegen auf den Wecker gehen). Schlussendlich führte folgende Codezeile – man beachte die unzähligen Backticks „`“ für die Fortsetzung der Zeile auf einer neuen Linie – zum Ziel:


$result | `
format-table `
@{label="Computername";`
expression={$_.Name.tolower()};`
width=16},`
@{label="Letzter Benutzer";`
expression={$_.LastLogonUserName};`
width=20},`
@{label="Letzte Agent-Kommunikation";`
expression={(([WMI] "").ConvertToDateTime(`
$($_.AgentTime | Sort-Object | Select-Object -Last 1)`
)).tostring("dd.MM.yyyy HH:mm:ss")};`
width=20}

Der Anfang dieser Zeile – ja es ist eine einzige Zeile! – ist nicht besonders schwierig zu verstehen. Der Inhalt von $result wird an den Befehl format-table übergeben, der dann die drei Datenfelder formatiert ausgibt, wobei die Definition eines Datenfeldes jeweils beim @ beginnt.

Bei den beiden ersten Spalten sind keine grossen Besonderheiten zu finden: Ich setze jeweils die gewünschte Spaltenüberschrift (label) und gebe mit dem jeweiligen Ausdruck (expression) den aktuellen ($_) Inhalt des jeweiligen Feldes aus, wobei ich noch die gewünschte Breite der Spalte (width) festlege. Beim Computernamen verwende ich zusätzlich noch die Funktion tolower(), da ich eine Liste mit Computernamen in Kleinbuchstaben lesbarer finde.

Die Expression für das Datum der letzten Kommunikation ist jedoch nicht mehr ganz so trivial; Ursache dafür ist die Tatsache, dass alle Zeitstempel im Format „yyyymmddHHMMSS.mmmmmmsUUU“ geliefert werden. Ich benutze deshalb die Funktion ConvertToDateTime, um daraus eine „brauchbare“ Zeit zu machen, die dann mit tostring("dd.MM.yyyy HH:mm:ss") in die gewünschte Darstellung umgewandelt wird.

Bleibt also noch die Zeile „$($_.AgentTime | Sort-Object | Select-Object -Last 1)“ zu erläutern: In SCCM ist AgentTime ein mehrwertiges Feld, d.h. es werden mehrere Zeitstempel gespeichert, wann ein Client mit dem Server gesprochen hat. Die gespeicherten Werte werden deshalb per Pipe an den Sortierer geschickt und dann der letzte (d.h. der neueste) Wert ausgewählt.

Klar: Dieses Skript ist nichts besonderes; es gibt in SCCM vordefinierte Reports, welche dieselbe Informationen (und noch mehr dazu) mit Hilfe weniger Mausklicks liefern können. Doch dieses Skript zeigt exemplarisch, wie so eine Query in Powershell realisiert werden könnte, womit diese auch als Basis für komplexere Abfragen dienen könnte.

Komplette Skriptdatei: computersystems.ps1 (zip)



Installation MS System Center Service Manager – Teil 6 – „Registration des Data Warehouse“
Samstag, 2. Januar 2010, 22:01
Abgelegt unter: Anleitungen | Tags: , , ,

In der Konsole finde ich im Bereich „Administration“ unter „Getting started“ im Kasten „Register with Service Manager’s Data Warehouse den Link „Register with Service Manager Data Warehouse“, den ich nun mal anklicke.

Kaum begonnen, schon klemmt es ein erstes Mal…

Damit wird der „Data Warehouse Registration Wizard“ gestartet, der mir seine Willkommensseite präsentiert. Nach dem ich auf „Next“ geklickt habe, werde ich nach dem Servernamen des Data Warehouse Management Server gefragt, zudem werde ich darauf hingewiesen, dass der aktuelle Benutzer administrative Rechte für diesen Server haben müsse. Ich trage den entsprechenden Servernamen ein und klicke sogleich mal auf „Test Connection“. Die Antwort lässt längere Zeit auf sich warten und lautet dann leider: „Unable to connect to the data warehouse management server“.

Im Deployment-Guide finde ich den Hinweis, dass der Service Manager Management Server über den TCP-Port 5724 auf den Data Warehouse Management Server zugreifen will. In der Firewall des Data Warehouse Management Server finde ich jedoch keine derartige Regel, die diese Verbindung erlauben würde. Zuversichtlich, die Ursache des Verbindungsproblems gefunden zu haben, erstelle ich deshalb eine entsprechende Regel auf dem Data Warehouse Management Server. Beim anschliessenden erneuten Klick auf „Test Connection“ kommt die Antwort sehr viel schneller und lautet obendrein: „Your connection to the data warehouse management server was successful“.

Im nächsten Dialog müssen nun die Credentials angegeben werden, mit welchen das Data Warehouse auf den Service Manager zugreifen soll; dieses müsse administrative Rechte auf diesem Server haben. Vorgeschlagen wird ein „Run as“-Konto in der Form „<Management Group Name> SecureReference“, weitere Alternativen werden mir nicht angeboten. Mir sagt das mal wieder rein gar nichts, zudem ist in der Liste der „Run As Accounts“ (zu finden in der Konsole unter „Administration“, „Security“) kein derartiges Konto verzeichnet.

Einmal mehr zeichnet mir ein Blogbeitrag aus Belgien einen möglichen Weg auf, der sich später als unnötig herausstellt. Im von Mike geposteten Screenshot erkenne ich, dass er hierzu das „Operational System Account“ verwendet. Ich wundere mich, weshalb das „Operational System Account“ nicht sowieso in der Auswahlliste auftaucht, vermute dann aber, dass mir hier die Sicht des Data Warehouse Management Servers angezeigt wird, der dieses Konto möglicherweise nicht kennt. Also klicke ich auf „New…“ und erstelle ein neues „Operational System Account“, wobei ich hier unser dafür vorgesehenes AD-Konto angebe. Der Wizard akzeptiert diese Angaben problemlos, weshalb ich hier auf „Next“ klicke.

Danach folgt noch die Summary-Seite, ein Klick auf „Create“ und einige Sekunden später kann ich lesen: „The data warehouse registration succeded.“ War es das schon wieder?

Nein, zu früh gefreut, denn einen kurzen Moment später poppt folgende Meldung auf:

The report deployment process has not completed.

Diese Meldung ist jedoch laut dem Deployment Guide zu erwarten. Einige Minuten nach dem Schliessen des Data Warehouse Registration Wizards werde in der Konsole innerhalb der Navigation ein zusätzlicher Eintrag für das Data Warehouse erscheinen. Dies ist bei mir der Fall.

Überprüfung der Installation

Der Deployment-Guide empfiehlt nun, die Data Warehouse Registration zu validieren. Dazu solle man folgendermassen vorgehen:

  1. Auf dem Data Warehouse Management Server eine Windows PowerShell mit administrativen Rechten starten
  2. Zuerst das Kommando „Add-PSSnapIn SMCmdletSnapIn“ ausführen
  3. Dann das Kommando „Get-SCDWMgmtGroup“ ausführen. Dieses müsse eine Tabelle mit zwei Zeilen ausgegeben, dabei müsse in der ersten Spalte einmal der Name der „Service Manager Management Group“ und einmal derjenige der „Data Warehouse Management Group“ zu sehen sein.

Auch das ist bei mir so gegeben. Um nun herausfinden zu können, ob der Management Pack Deployment Prozess abgeschlossen worden ist, muss laut Deployment-Guide folgendermassen vorgegangen werden:

  1. Service Manager Konsole starten und den Abschnitt „Data Warehouse“ wählen.
  2. Navigieren zu „Data Warehouse“, „Data Warehouse Jobs“.
  3. Den „MPSyncJob“ auswählen und die Details anzeigen lassen.
  4. In der erscheinenden Ansicht solle man nach rechts scrollen und die Spalte „Status“ kontrollieren. Der Deployment Prozess sei dann abgeschlossen, wenn bei allen Management Packs entweder „Associated“ oder „Imported“ angezeigt werde. Es dürfe nirgends mehr „Pending Associations“ oder gar „Failed“ stehen.

Doch bei mir ist diese Liste schlicht und einfach leer. Es wird mir kein einziges Management Pack angezeigt. Was nun?

Troubleshooting

Die Suche im Internet fördert eine Diskussion in den MS Technet Foren zum Thema
„Service Manager Data Warehouse is registered and MPSync Job is running but has empty details“ zu Tage. In dieser Diskussion wird eingeräumt, dass es noch Probleme gebe mit der Globalisierung des Produktes. Kurz zusammengefasst lautet die Empfehlung dieser Diskussion, dass man das „Format“ und das „System Locale“ auf „English (United States)“ einstellen solle. Ich habe unsere Server zwar mit der englischen Sprachversion des Betriebssystems installiert, doch hier war wie bei uns üblich an beiden Orten „German (Switzerland)“ eingetragen. Ich passe deshalb bei beiden Servern die entsprechenden Einstellungen an und führe danach den notwendigen Neustart durch.

Nach dem Neustart öffne ich wieder die Konsole und navigiere wieder zu „Data Warehouse“, „Data Warehouse Jobs“ und öffne erneut die Details des „MPSyncJob“. Und tatsächlich: Jetzt ist die Liste der Management Packs lesbar, doch der Vorgang ist noch längst nicht abgeschlossen.

Mit der Zeit tauchen nun weitere Data Warehouse Jobs in der Konsole auf, doch es bleibt bei vier Einträgen, obwohl es laut Deployment-Guide deren fünf werden müssten: Der Eintrag in der Form „Extract_<Service Manager management group name>“ fehlt in der Liste. Wo klemmts jetzt schon wieder?

Nach längerem Suchen entdecke ich auf dem Data Warehouse Management Server im Event-Log des Operations Manager (ja genau: Operations Manager!) einige Error-Einträge: Beim näheren Studium der Fehlermeldungen klingelt die Glocke im Hinterkopf, als ich im länglichen Text eines Errorseintrages auf folgendes stosse: „Could not connect to net.tcp://<Service Manager Management Server>:5724/DispatcherService.“ Die Windows Firewall muss nicht nur auf dem Data Warehouse Management Server, sondern auch auf dem Service Manager Management Server den Zugang über den TCP-Port 5724 erlauben! Flugs habe ich auch auf diesem Server die entsprechende Regel definiert und nochmals den „MPSyncJob“ angestossen. Es dauert nicht lange, da taucht auch der fünfte, vermisste Data Warehouse Job in der Liste auf. Jetzt läuft auch der „MPSyncJob“ wieder deutlich länger, muss er doch – wie ein Blick auf die Details zeigt – nochmals eine weitere grosse Zahl an Management Packs verarbeiten.

Etliche Zeit später ist der Job endlich erfolgreich durchgelaufen. Ich schliesse die Konsole ein weiteres Mal und starte sie sogleich wieder. Erstmals bleibt nun die oben gezeigte Meldung aus, dafür findet sich in der Navigationsspalte nochmals ein weiterer Eintrag namens „Reporting“. Endlich sieht bei mir die Service Manager Konsole so aus, wie ich sie gemäss der Lektüre des Blogbeitrag von Mike aus Belgien erwartet habe. Bin ich nun endlich fertig?

Der Deployment-Guide meint: leider nein.

Es geht weiter…

Gemäss Deployment-Guide sind nämlich für die Extract, Transform und Load-Jobs die Schedules nicht noch aktiviert, was sich in der aktuellen Beta 2 noch nicht über die grafische Oberfläche bewerkstelligen lässt; dazu muss einmal mehr die Powershell herhalten. Zudem sei es noch nicht möglich, den Status eines bestimmten Jobs abzufragen: Wenn man den Status eines Jobs wissen müsse, dann solle man einfach den Befehl erteilen, diesen zu aktivieren.

Für die Aktivierung der Job-Schedules ist gemäss Deployment Guide folgendes Vorgehen nötig:

  1. Auf dem Data Warehouse Management Server eine Powershell mit administrativen Rechten starten:
  2. Zuerst das Kommando „Add-PSSnapIn SMCmdletSnapIn“ ausführen
  3. dann nötigenfalls das Kommando „Set-ExecutionPolicy RemoteSigned“ absetzen
  4. dann folgende 4 Befehle ausführen:
    Enable-SCDWJobSchedule –JobName Extract_<data warehouse management group name>

    Enable-SCDWJobSchedule –JobName Extract_<Service Manager management group name>

    Enable-SCDWJobSchedule –JobName Transform

    Enable-SCDWJobSchedule –JobName Load

Damit sind wir nun endlich durch und die Registration des Data Warehouse ist abgeschlossen.

Lessons learnt – Gelernte Lektionen

Zusammenfassend kann ich folgende Punkte festhalten, die man unbedingt beachten sollte, damit die Registration des Data Warehouse am Service Manager reibungslos ablaufen kann:

  • Der TCP-Port 5724 muss in der Windows-Firewall auf allen beteiligten Service Manager Servern geöffnet sein, damit diese miteinander kommunizieren können.
  • Das vorgeschlagene Konto „<Management Group Name> SecureReference“, das vom „Data Warehouse Registration Wizard“ vorgeschlagen wird, müsste grundsätzlich ausreichen. Denn als ich mal zufälligerweise auch in den Bereich „Data Warehouse“, „Security“, „Run As Accounts“ einen Blick riskierte, habe ich dort dieses Konto entdeckt: Es verwendet nämlich exakt dasselbe AD-Konto, welches ich im zusätzlich erstellten „Operational System Account“ angegeben habe. Da war der Wizard wieder mal schlauer als ich. 🙂
  • Die Regional Settings und das „System Locale“ sollten (zumindest noch jetzt bei der Beta 2) auf „English (United States)“ gesetzt sein; dies kann eine Menge Probleme ersparen…


Bereitstellung von Gerätetreibern (Teil 3: Installation via „Apply Driver Package“)
Dienstag, 15. Dezember 2009, 22:25
Abgelegt unter: Anleitungen | Tags: , , , ,

Damit nun das neue Treiberpaket gezielt nur auf bestimmte Systeme installiert werden kann, müssen wir noch herausfinden, wie die genauen Werte lauten, welche wir für die entsprechende Condition verwenden können. Dies lässt sich natürlich über den „Ressource Explorer“ in der SCCM-Konsole herausfinden, aber dank der Powershell geht das noch viel einfacher: Einfach auf dem betreffenden Gerät eine Powershell öffnen und das Kommando


get-WMIObject Win32_ComputerSystem

ausführen. Die Ausgabe umfasst dann etwa ein halbes Dutzend Zeilen, doch die beiden Werte für „Manufacturer“ und „Model“ interessieren uns besonders. Hier zwei Beispiele:


Manufacturer : Hewlett-Packard
Model : HP Compaq dc7800 Convertible Minitower


Manufacturer : IBM
Model : 1869CNG

Hier sehen wir also sehr gut, dass wir problemlos erkennen können, ob wir nun einen HP DC7800 Minitower oder ein älteres IBM-Notebook vor uns haben. Diese Information können wir nun für die Formulierung der Condition für die Installation des jeweiligen Treiberpaketes verwenden.

Somit können wir nun in der SCCM-Konsole die Tasksequenz erweitern, welche zur Installation des betreffenden Gerätes verwendet wird. Hier lohnt es sich, zuerst einen Ordner „Apply Drivers“ zu definieren, in welchem alle Tasksequenzschritte für die Installation von Treiberpaketen gesammelt werden können. In diesem Ordner können wir nun einen zusätzlichen Schritt vom Typ „Apply Driver Package“ hinzufügen; als dessen Name setzen wir jeweils die Kombination von „Manufacturer“ und „Model“, damit wir eine übersichtliche Liste der Tasksequenz-Schritte für die Installation von Treiberpaketen für die verschiedenen Gerätetypen erhalten.

Als „Driver Package“ wählen wir nun das neue Treiberpaket, das wir gemäss dem letzten Blogbeitrag erstellt haben. Unter „Options“ empfiehlt es sich, gleich mal das Häckchen bei „Continue on Error“ zu setzen, dann können wir eine sog. „WMI-Query“ hinzufügen, der dazu benötigte WMI-Namespace ist „root\cimv2“. Hierzu wieder zwei Beispiele:


SELECT * FROM Win32_ComputerSystem
WHERE Manufacturer = "Hewlett-Packard"
AND Model = "HP Compaq dc7800 Convertible Minitower"


SELECT * FROM Win32_ComputerSystem
WHERE Manufacturer = "IBM"
AND Model = "1869CNG"

Wie unschwer zu erkennen ist, sind in der Query genau die beiden Werte für Manufacturer und Model einzutragen, die der eingangs beschriebene Powershell-Befehl ausgegeben hat. Auf diese Weise wird bei der ersten Query das Treiberpaket nur auf dem HP DC7800 und beim zweiten Beispiel nur auf dem älteren IBM-Notebook installiert. Haben wir die Tasksequenz auf diese Weise ergänzt, kann nun damit das Gerät nochmals neu installiert werden; dabei sollte nun das neue Treiberpaket bei den passenden Geräten mitinstalliert werden.

Damit haben wir nun unser Ziel erreicht, gezielt einzelne Treiberpakete für bestimmte Gerätetypen zur Verfügung zu stellen. Wir können nun genau definieren, welche Treiber ein bestimmtes Gerätemodell zu installieren hat, und vermeiden somit unerwartete Nebeneffekte, die ein „Auto Apply Drivers“ auslösen kann.

Wer nun allerdings befürchtet, nun den neuen Tasksequenzschritt vom Typ „Apply Driver Package“ in unzähligen verschiedenen Tasksequenzen einpflegen zu müssen, liegt leider nicht ganz falsch. Ich habe auch noch keinen Weg gefunden, wie man dies komplett vermeiden kann. Immerhin hat jedoch kürzlich einer meiner Kollegen zufälligerweise entdeckt, dass man einzelne Tasksequenzschritte (bzw. ganze Ordner von Tasksequenzschritten) wunderbar per „Drag and Drop“ (mit gedrückter CTRL-Taste!) von einem Tasksequence-Editorfenster zum anderen kopieren kann. Somit entfällt wenigstens das mehrfache Erstellen desselben Tasksequenzschrittes in verschiedenen Tasksequenzen; einmal erstellen reicht, dann kann wenigstens kopiert werden. Diesen kleinen Tipp zum Schluss dieser dreiteiligen Reihe wollte ich Euch nicht vorenthalten.

Frohe Festtage
Euer Michael Hottinger