Hey, Scripting Guy!Auch nicht so harte Arbeit hat ihren Lohn

Die Scripting Guys von Microsoft

Laden Sie den Code für diesen Artikel herunter: HeyScriptingGuy2008_06.exe (150KB)

Seit Hunderten von Jahren sind Menschen der Überzeugung, dass harte Arbeit Lohn an sich ist, dass ein Tag ehrliche Arbeit zu wahrer Befriedigung führt, dass nicht die Reise, sondern das Ziel wahres Glück bringt, dass ... Sie verstehen schon, worauf wir hinauswollen. Arbeiten Sie hart, ohne sich zu beklagen (denken Sie nur an das Aschenputtel), und irgendwann werden Sie Ihren gerechten Lohn erhalten.

Hinweis: Stimmt es wirklich, dass harte Arbeit nicht nur glücklicher macht, sondern dass Sie irgendwann für Ihre Bemühungen auch belohnt werden? Weshalb stellen Sie uns diese Frage?

Natürlich hatte das Aschenputtel Glück. Schließlich bieten sich alle möglichen Gelegenheiten für harte Arbeit, wenn man bei einer bösen Stiefmutter und boshaften Stiefschwestern lebt. Und wenn man dieses Glück nicht hat? Angenommen Sie leben nicht bei einer bösen Stiefmutter und boshaften Stiefschwestern. Wie können Sie dann lange, zermürbende, undankbare Tage mit harter Arbeit verbringen? Wie werden Sie jemals wahres Glück finden?

Also, wenn Sie fest entschlossen sind, Knochenarbeit zu leisten, sollten Sie sich laut Meinung der Scripting Guys am Schreiben eines Skripts versuchen, das Daten in einem schönen, ordentlichen Tabellenformat ausgibt, wie es die Ausgabe in Abbildung 1 zeigt.

Abbildung 1 Ausgabe im Tabellenformat

Abbildung 1** Ausgabe im Tabellenformat **(Zum Vergrößern auf das Bild klicken)

Wie bereits erwähnt: das Aschenputtel hatte sehr viel Glück. Es durfte das Haus gründlich putzen und am Herd inmitten von Asche und Ruß sitzen, wenn es fertig war. Doch selbst das Aschenputtel hätte protestiert, wenn es ein Skript hätte schreiben müssen, das Daten im Tabellenformat anzeigen kann. Inmitten von Asche und Ruß zu sitzen ist eine Sache. Ein Skript zu schreiben, das Daten im Tabellenformat ausgibt, etwas ganz anderes.

Hinweis: Es sei denn, Sie müssen beim Schreiben Ihrer Skripts am Herd sitzen. Dann läuft es so ziemlich auf dasselbe hinaus.

Warum würde das Aschenputtel vor dieser Aufgabe zurückscheuen? Ganz einfach: sie ist viel zu schwierig. Die einzige Möglichkeit, Daten im Tabellenformat in VBScript anzuzeigen, besteht darin, etwas Ähnliches wie dies vorzunehmen:

  • Zuerst legen Sie die maximale Größe für jede Spalte fest. Der Anzeigename eines Diensts soll beispielsweise 52 Zeichen lang sein.
  • Davon ausgehend berechnen Sie die Anzahl der Zeichen in einem Datenelement. Der Anzeigename „Adobe LM Service“ beispielsweise hat 16 Zeichen.
  • Wenn der Anzeigename die 52-Zeichen-Grenze überschreitet, legen Sie die Anzahl von Zeichen fest, die am Ende der Zeichenfolge abgeschnitten werden müssen, damit sie in den zugewiesenen Raum passt. Wenn der Anzeigename 52 Zeichen nicht überschreitet, legen Sie fest, wie viele Leerstellen am Ende der Zeichenfolge hinzugefügt werden müssen, damit sie genau 52 Zeichen lang ist.
  • Wiederholen Sie das Ganze für den nächsten Datensatz. Und für den nächsten. Und so weiter.

Wenn Sie mit der Geschichte vom Aschenputtel vertraut sind, wissen Sie, dass möglicherweise die gute Fee unangemeldet vorbeikommt, eine Maus in einen Systemadministrator verwandelt (kein Kommentar dazu, wie einfach das sein könnte) und diese Maus dann dieses Skript für Sie schreibt. Aber Sie sollten sich lieber nicht darauf verlassen, dass dies geschieht. Wahrscheinlich müssen Sie es schon selbst tun,

wobei Sie wahrscheinlich der zufriedenste Mensch der Welt sind. Und auch der am härtesten arbeitende Mensch. Ohne Übertreibung.

Wahrscheinlich wird so mancher gewillt sein, auf ein wenig Befriedigung zu verzichten, wenn er dafür nicht ganz so schwer arbeiten muss. Wenn Sie zu diesen Menschen gehören, denken Sie wahrscheinlich: „Zum Glück gibt es ja die Scripting Guys. Sie werden mir zeigen, wie eine Maus in einen Systemadministrator verwandelt wird, und mir dann sagen, wie ich die Maus dazu bringen kann, meine Ausgabe als Tabelle zu formatieren.“ Leider haben wir keine guten Nachrichten für Sie: Die Scripting Guys haben absolut keine Ahnung, wie eine Maus in einen Systemadministrator verwandelt wird. (Obwohl wir einen Systemadministrator in eine Maus verwandeln können, wenn das für Sie irgendwie nützlich ist.) Wir wissen nicht, wie Sie irgend jemanden dazu bringen können, Skripts für Sie zu schreiben, ganz abgesehen von Skripts, die Daten im Tabellenformat ausgeben.

Aber das ist ok. Solange Sie Windows® XP oder Windows Server® 2003 ausführen (was bei vielen von Ihnen der Fall ist), brauchen Sie keine Maus, die Ihre Skripts für Sie schreibt. (Nein, tut uns Leid – es funktioniert leider nicht unter Windows Vista®.) Stattdessen können Sie es mit wenig Aufwand dank des Microsoft.CmdLib-Objekts selbst tun. Sehen Sie sich das Beispielskript in Abbildung 2 an.

Figure 2 Erstellen einer Tabellenanzeige

Dim arrResultsArray()
i = 0

Set objCmdLib = _
  CreateObject("Microsoft.CmdLib")
Set objCmdLib.ScriptingHost = _
  WScript.Application

arrHeader = Array("Display Name", _
  "State", "Start Mode")
arrMaxLength = Array(52, 12, 12)
strFormat = "Table"
blnPrintHeader = True
arrBlnHide = Array(False, False, False)

strComputer = "."

Set objWMIService = GetObject("winmgmts:\\" _
  & strComputer & "\root\cimv2")

Set colServices = objWMIService.ExecQuery _
  ("Select * FROM Win32_Service")

For Each objService In colServices
  ReDim Preserve arrResultsArray(i)
  arrResultsArray(i) = _
  Array(objService.DisplayName, _
    objService.State,objService.StartMode)
  i = i + 1
Next
objCmdLib.ShowResults arrHeader, _
  arrResultsArray, arrMaxLength, _
  strFormat, blnPrintHeader, arrBlnHide

Falls Sie sich wundern: Microsoft.CmdLib ist ein COM-Objekt, das mit Windows XP und Windows Server 2003 geliefert wird. Dieses Objekt hat eine Reihe verschiedener Features. Um weitere Informationen zu erhalten, geben Sie „cmdlib.wsc /?“ in der Eingabeaufforderung ein und lesen die Kommentare in der auf dem Bildschirm angezeigten Skriptdatei. An dieser Stelle soll jedoch nur ein Feature von Microsoft.CmdLib behandelt werden: die Möglichkeit, Daten im Tabellenformat anzuzeigen.

Dies führt zu einer offensichtlichen Frage: Wie werden Daten im Tabellenformat angezeigt? Mal sehen, ob wir das herausfinden können. Wie Sie sehen, steht am Anfang des Beispielskripts eine Definition eines dynamischen Arrays mit der Bezeichnung arrResultsArray:

Dim arrResultsArray()

In einem typischen Skript werden Daten auf dem Bildschirm so schnell zurückgegeben, wie sie abgerufen werden. Doch es ist nicht zu erwarten, dass die Scripting Guys etwas auf normale Art und Weise tun. In diesem Skript werden die Daten nicht zurückgegeben, sobald sie abgerufen werden. Stattdessen werden alle zurückgegebenen Daten in einem Array gespeichert und mithilfe von Microsoft.CmdLib formatiert und angezeigt.

Anders ausgedrückt: Dies ist der Grund, warum zunächst ein dynamisches Array erstellt wird (also ein Array, dessen Größe im Verlauf des Skripts geändert werden kann). Nach dem Definieren des Arrays legen Sie den Wert einer Gegenvariablen mit der Bezeichnung „i“ auf 0 fest. Sie verwenden diese Variable, um die aktuelle Größe des Arrays zu verfolgen.

Falls Sie sich wundern: Der Wert von „i“ wurde auf 0 festgelegt, weil das erste Element in einem Array immer die Indexziffer 0 erhält. Wenn Sie dem Array dann das erste Element hinzufügen, fügen Sie also Element 0 statt Element 1 hinzu.

Als Nächstes müssen Sie die Instanz des Microsoft.CmdLib-Objekts initialisieren. Dies erfolgt mithilfe dieser beiden Codezeilen:

Set objCmdLib = _
CreateObject("Microsoft.CmdLib")
Set objCmdLib.ScriptingHost = WScript.Application

Das führt zu diesem kleinen Codeblock:

arrHeader = Array("Display Name", "State", "Start Mode")
arrMaxLength = Array(52, 12, 12)
strFormat = "Table"
blnPrintHeader = True
arrBlnHide = Array(False, False, False)

Hier werden ein paar Parameter zum Konfigurieren der Ausgabe eingerichtet. In der ersten Zeile weisen Sie einem Array mit der Bezeichnung „arrHeader“ Werte zu. Wie zu erwarten, sind dies die Überschriften für die einzelnen Spalten der Ausgabetabelle. Für dieses Beispielskript rufen Sie Informationen zu den Diensten ab, die auf einem Computer ausgeführt werden. Anschließend zeigen Sie die Werte der Eigenschaften „DisplayName“, „State“ und „Start Mode“ der einzelnen Dienste an.

Es überrascht nicht weiter, dass dem Array die Spaltennamen „Display Name“, „State“ und „Start Mode“ zugewiesen werden (obwohl sie auch A, B und C, Larry, Moe und Curly oder irgendetwas anderes genannt werden könnten, da die Spaltennamen nicht identisch mit den Eigenschaftsnamen sein müssen).

Hinweis: Es gibt (auch in Bezug auf die Namen der Stiefschwestern) viele Variationen des Märchens vom Aschenputtel. In der Disney-Version „Cinderella“ heißen die Stiefschwestern Drizzella und Anastasia, und ganz zufällig lauten der erste und zweite Vorname unseres Scripting Editors genauso!

In der zweiten Codezeile weisen Sie einem anderen Array mit der Bezeichnung arrMaxLength Werte zu. Dieses Array nimmt die Größe jeder Spalte in der Tabelle auf. In unserer Ausgabe sollen Spalte 1 (der Dienstanzeigename) 52 Zeichen zugeordnet werden. Dem Dienstzustand und dem Startmodus sollen dann jeweils 12 Zeichen zugeordnet werden. (Microsoft.CmdLib fügt automatisch eine Leerstelle zwischen den Spalten ein.) Wenn die Spaltengrößen 52, 12 und 12 Zeichen betragen sollen (was der Fall ist), verwenden Sie den folgenden Code:

arrMaxLength = Array(52, 12, 12)

Die dritte Zeile gibt das Ausgabeformat für die Daten an. Die Daten sollen als Tabelle angezeigt werden. Daher wird der Wert „strFormat“ (die Variable, die den Ausgabetyp enthält) auf „Table“ festgelegt. Angenommen die Daten sollen stattdessen als eine durch Komma getrennte Werteliste angezeigt werden. In diesem Fall würde das Format so auf CSV festgelegt:

strFormat = "CSV"

Dabei erhalten Sie eine Ausgabe ähnlich der folgenden:

"Display Name","State","Start Mode"
"Adobe LM Service","Stopped","Manual"
"Adobe Active File Monitor V4","Stopped","Manual"
"Alerter","Stopped","Manual"
"Application Layer Gateway Service","Running","Manual"
"Apple Mobile Device","Running","Auto"
"Application Management","Stopped","Manual"

Beachten Sie, dass Microsoft.CmdLib nicht nur Kommas zwischen die einzelnen Elemente, sondern die einzelnen Werte auch in doppelte Anführungszeichen gesetzt hat. Dieses Feature ist nützlicher, als Sie vielleicht zuerst denken. Schließlich müssten Sie bei manueller Erstellung Code verwenden, der folgendermaßen aussieht:

Wscript.Echo Chr(34) & objService.DisplayName & Chr(34) & "," & Chr(34) & objService.State & Chr(34) & "," & Chr(34) & objService.StartMode & Chr(34)

Oje.

Was ist los? Sie mögen keine Tabellen, aber auch nicht das CSV-Format? Nun, in diesem Fall könnte das Format auf „List“ festgelegt werden, sodass Sie eine Ausgabe ähnlich der folgenden erhalten:

Display Name: Adobe LM Service
State:        Stopped
Start Mode:   Manual
Display Name: Adobe Active File Monitor V4
State:        Stopped
Start Mode:   Manual

Doch wir schweifen vom Thema ab. (Was wir ja hin und wieder gerne tun.) Nach Definieren des Ausgabeformats legen Sie den Wert einer Variablen mit dem Namen „blnPrintHeader“ auf „True“ fest:

blnPrintHeader = True

Sie verwenden „blnPrintHeader“, damit Microsoft.CmdLib die Spaltenüberschriften druckt. Was passiert aber, wenn die Spaltenüberschriften nicht gedruckt werden sollen? Kein Problem – in diesem Fall wird „blnPrintHeader“ auf „False“ festgelegt:

blnPrintHeader = False

Schließlich liegt diese Codezeile vor:

arrBlnHide = Array(False, False, False)

Wenn Ihre Daten nun angezeigt werden sollen, bietet Microsoft.CmdLib die Option, eine Spalte ein- oder auszublenden. Zum Ausblenden einer Spalte (also zum Unterdrücken von Daten für eine bestimmte Eigenschaft), wird der Wert für diese Eigenschaft auf „True“ festgelegt. Zum Einblenden einer Spalte, wird der Wert auf „False“ festgelegt.

In dieser Ausgabe werden die Werte für die Eigenschaften „DisplayName“, „State“ und „StartMode“ angezeigt, und zwar in dieser Reihenfolge. Daher werden in diesem Array die Werte „False“, „False“ und „False“ verwendet Wie gehen Sie vor, wenn DisplayName eingeblendet, State ausgeblendet und StartMode eingeblendet werden soll? In diesem Fall verwenden Sie diese Codezeile:

arrBlnHide = Array(False, True, False)

„False“ wird also zum Einblenden einer Spalte und „True“ zum Ausblenden verwendet.

Jetzt sind die Scripting Guys bereit, einige Daten auszugeben, d. h., sie wären bereit dazu, wenn sie Daten hätten. (Haben die Scripting Guys je ein Skript geschrieben, das keine Daten ausgegeben hat, dann übermäßig viel Zeit zum Debuggen dieses Skripts aufgewendet, nur um dann festzustellen, dass ursprünglich überhaupt keine Daten abgerufen wurden? Selbstverständlich nicht – wie kommen Sie nur auf diese Idee?)

Der nächste Schritt besteht also darin, eine Bindung mit dem Windows-Verwaltungsinstrumentationsdienst (Windows Management Instrumentation, WMI) auf dem lokalen Computer herzustellen und dann die ExecQuery-Methode zum Abrufen von Informationen zu allen auf diesem Computer installierten Diensten zu verwenden.

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colServices = objWMIService.ExecQuery ("Select * FROM Win32_Service")

Wir sollten wahrscheinlich erwähnen, dass Sie hier nicht darauf beschränkt sind, mit WMI-Daten zu arbeiten. Wie zu erwarten ist, kann Microsoft.CmdLib mit beliebigen Daten arbeiten. WMI ist nur eine praktische Möglichkeit, alle möglichen Daten abzurufen.

Wenn eine Sammlung dienstbezogener Daten vorliegt, wird eine „For Each“-Schleife eingerichtet, die alle Dienste in der Sammlung durchläuft. Doch statt die Eigenschaftswerte für jeden Dienst wiederzugeben, wird dieser Code ausgeführt:

ReDim Preserve arrResultsArray(i)
arrResultsArray(i) = Array(objService.DisplayName, objService.State,objService.StartMode)
i = i + 1

Was wird mit diesem Codeblock gemacht? In Zeile 1 wird die Größe des Arrays mithilfe des Befehls „ReDim Preserve“ geändert, wobei nicht nur die Größe des Arrays geändert wird, sondern auch vorhandene Daten im Array beibehalten werden. (Ohne das Schlüsselwort „Preserve“ würde die Größe des Arrays geändert, aber derzeit im Array vorhandene Daten würden gelöscht.)

Welche Größe soll das Array erhalten? In der ersten Schleife wird ein Array der Größe 0 erstellt, d. h. ein Array, das ein Element enthält. Wie lässt sich aber mit Sicherheit sagen, dass ein Array der Größe 0 erstellt wird? Weil die Gegenvariable „i“ verwendet wird, die 0 entspricht.

Wenn die Variable „i“ verwendet wird, um die Größe des Arrays zu repräsentieren, bedeutet dies dann nicht, dass die Größe immer auf 0 festgelegt wird? Das wäre tatsächlich der Fall, doch jedes Mal, wenn die Schleife durchlaufen wird, erhöht sich der Wert „i“ um 1. Wie Sie sehen, geschieht genau das in Zeile 3 des Codeblocks.

Jetzt müssen Sie sich nur noch um eine Codezeile kümmern:

arrResultsArray(i) = Array(objService.DisplayName, objService.State,objService.StartMode)

Hier werden einfach die Eigenschaftswerte, die von Interesse sind (DisplayName, State und StartMode) dem Array „arrResultsArray“ hinzugefügt. Beachten Sie, dass die Eigenschaftswerte nicht einzeln, sondern als ein Array von Werten hinzugefügt werden. Zugegeben, das ist ein wenig ungewöhnlich: Es bedeutet, dass jedes Element im Array „arrResultsArray“ ein anderes Array ist, aber so funktioniert Microsoft.CmdLib nun mal.

Das könnte natürlich dazu führen, dass Sie sich wieder Gedanken machen. „Ein Array von Arrays? Wie um alles in der Welt soll ich auf all die einzelnen Werte in einem Array voller Arrays zuzugreifen können?“ Geraten Sie nicht in Panik. Es ist ganz einfach: Microsoft.CmdLib erledigt dies alles für Sie.

Hinweis: Leider ist das Zugreifen auf alle einzelnen Werte in einem Array von Arrays so ziemlich das Einzige, das Microsoft.CmdLib für Sie tun kann. Das Putzen und Geschirrspülen für die böse Stiefmutter sowie das Schneidern der Kleider für die boshaften Stiefschwestern werden für die nächste Version des Objekts in Betracht gezogen.

Tatsächlich können Sie die Daten (im ordentlichen Tabellenformat) ausgeben, indem einfach die ShowResults-Methode aufgerufen wird und der Methode alle zuvor im Skript konfigurierten Arrays und Variablen übergeben werden:

objCmdLib.ShowResults arrHeader, arrResultsArray, arrMaxLength, strFormat, blnPrintHeader, arrBlnHide

Wie sieht das Ergebnis dann aus? Es sieht genau wie die ordentlich formatierte Ausgabe aus, die wir uns beim Betrachten von Abbildung 1 erhofft hatten.

Nicht schlecht, oder? Sie erhalten eine ordentliche Ausgabe und mussten fast nichts dazu tun. (Ihr nächstes Skript wird sogar noch einfacher, da Sie nur einige kleine Änderungen an diesem ersten Skript vornehmen müssen.)

Zugegebenermaßen bietet Ihnen das nicht dieselbe Befriedigung, die das Aschenputtel aufgrund seiner Schufterei tagein und tagaus hatte, nur damit es Skript in einer Tabelle ausgeben konnte. Sie werden wahrscheinlich auch keinen Prinzen heiraten dürfen, denn das ist nun wirklich nicht Teil der Abmachung. Aber das scheint ein geringer Preis in Anbetracht der ordentlichen Ausgabe mithilfe eines VBScript-Skripts, besonders dann, wenn Sie sich vor Augen führen, wie Prinzen heute so sind.

Und wer weiß: vielleicht bekommen Sie Ihren Prinzen trotzdem. Schließlich brauchen selbst königliche Personen Informationen über all die Dienste, die auf ihren Computern installiert sind.

Der Scripting Perplexer von Dr. Scripto

Die monatliche Herausforderung, die nicht nur Ihr Talent zum Rätsellösen testet, sondern auch Ihre Skriptingfähigkeiten.

Juni 2008: PowerShell-Pfad

In jedem dieser Rätsel verbinden Sie die Buchstaben waagerecht, senkrecht und diagonal, um den Namen eines Windows PowerShell-Cmdlet zu erhalten. Jeder Buchstabe wird nur ein Mal verwendet. Hier ist ein Beispiel:

Das in diesem Rätsel erstellte Cmdlet heißt New-Alias. Jetzt sind Sie an der Reihe. Hier sind noch drei Rätsel:

ANSWER:

Der Scripting Perplexer von Dr. Scripto

Antworten: PowerShell-Pfad, Juni 2008

Read-Host

Set-AuthenticodeSignature

Die Scripting Guys von Microsoft arbeiten für Microsoft (oder sind zumindest dort angestellt). Wenn sie nicht gerade ihrem Hobby, dem Baseball (oder verschiedenen anderen Aktivitäten) nachgehen, betreiben sie das TechNet-Skriptcenter. Besuchen Sie es unter www.scriptingguys.com.

© 2008 Microsoft Corporation und CMP Media, LLC. Alle Rechte vorbehalten. Die nicht genehmigte teilweise oder vollständige Vervielfältigung ist nicht zulässig.