[How-To]MOF->WMI->Registry

Xaero1982

Well-Known Member
#1
Hallo,

zunächst möchte ich allen Interessenten ein paar Links ans Herz legen:
WMI:
http://www.microsoft.com/germany/msdn/library/windows/api/LeitfadenFuerWMISkriptingTeil1.mspx
http://www.microsoft.com/germany/msdn/library/windows/api/LeitfadenFuerWMISkriptingTeil2.mspx
http://www.microsoft.com/germany/msdn/library/windows/api/WMIAlsHilfeZurSelbsthilfe.mspx?mfr=true
MOF:
http://www.microsoft.com/germany/technet/datenbank/articles/600682.mspx
Tools:
WMI Tools
WMI Scriptomatic 2.0

MOF?
WMI?

Nie gehört?

Tja, also um es kurz zu machen:

Die WMI (Windows Management Instrumentation) ist seit Windows ME Standardmäßig bei Windows dabei. Ohne WMI läuft Windows nicht!
Was aber ist WMI?
WMI ist ein "Tool", mit dem man:

1. Inventardaten von Hardware und Software verwalten (WMI Repository)
2. Computer (re)booten
3. Dienste und Warteschlangen abfragen, starten, beenden
4. Ereignisprotokolle und Performance Logs lesen, konfigurieren, löschen
5. Registry bearbeiten
6. Programme starten

kann.

Ich werde in meinem kleinen Tutorial nicht auf tiefer auf WMI an sich eingehen, sondern eher auf die MOF Dateien.

Eine MOF - Datei dient dazu selbst Abfragen zu erstellen und diese dem WMI Namespace hinzuzufügen.

Ein Beispiel zu WMI:

Code:
On Error Resume Next

Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20

arrComputers = Array(".")
For Each strComputer In arrComputers
   WScript.Echo
   WScript.Echo "=========================================="
   WScript.Echo "Computer: " & strComputer
   WScript.Echo "=========================================="

   Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
   Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem", "WQL", _
                                          wbemFlagReturnImmediately + wbemFlagForwardOnly)

   For Each objItem In colItems
      WScript.Echo "AdminPasswordStatus: " & objItem.AdminPasswordStatus
      WScript.Echo "AutomaticResetBootOption: " & objItem.AutomaticResetBootOption
      WScript.Echo "AutomaticResetCapability: " & objItem.AutomaticResetCapability
      WScript.Echo "BootOptionOnLimit: " & objItem.BootOptionOnLimit
      WScript.Echo "BootOptionOnWatchDog: " & objItem.BootOptionOnWatchDog
      WScript.Echo "BootROMSupported: " & objItem.BootROMSupported
      WScript.Echo "BootupState: " & objItem.BootupState
      WScript.Echo "Caption: " & objItem.Caption
      WScript.Echo "ChassisBootupState: " & objItem.ChassisBootupState
      WScript.Echo "CreationClassName: " & objItem.CreationClassName
      WScript.Echo "CurrentTimeZone: " & objItem.CurrentTimeZone
      WScript.Echo "DaylightInEffect: " & objItem.DaylightInEffect
      WScript.Echo "Description: " & objItem.Description
      WScript.Echo "Domain: " & objItem.Domain
      WScript.Echo "DomainRole: " & objItem.DomainRole
      WScript.Echo "FrontPanelResetStatus: " & objItem.FrontPanelResetStatus
      WScript.Echo "InfraredSupported: " & objItem.InfraredSupported
      strInitialLoadInfo = Join(objItem.InitialLoadInfo, ",")
         WScript.Echo "InitialLoadInfo: " & strInitialLoadInfo
      WScript.Echo "InstallDate: " & WMIDateStringToDate(objItem.InstallDate)
      WScript.Echo "KeyboardPasswordStatus: " & objItem.KeyboardPasswordStatus
      WScript.Echo "LastLoadInfo: " & objItem.LastLoadInfo
      WScript.Echo "Manufacturer: " & objItem.Manufacturer
      WScript.Echo "Model: " & objItem.Model
      WScript.Echo "Name: " & objItem.Name
      WScript.Echo "NameFormat: " & objItem.NameFormat
      WScript.Echo "NetworkServerModeEnabled: " & objItem.NetworkServerModeEnabled
      WScript.Echo "NumberOfProcessors: " & objItem.NumberOfProcessors
      strOEMLogoBitmap = Join(objItem.OEMLogoBitmap, ",")
         WScript.Echo "OEMLogoBitmap: " & strOEMLogoBitmap
      strOEMStringArray = Join(objItem.OEMStringArray, ",")
         WScript.Echo "OEMStringArray: " & strOEMStringArray
      WScript.Echo "PauseAfterReset: " & objItem.PauseAfterReset
      strPowerManagementCapabilities = Join(objItem.PowerManagementCapabilities, ",")
         WScript.Echo "PowerManagementCapabilities: " & strPowerManagementCapabilities
      WScript.Echo "PowerManagementSupported: " & objItem.PowerManagementSupported
      WScript.Echo "PowerOnPasswordStatus: " & objItem.PowerOnPasswordStatus
      WScript.Echo "PowerState: " & objItem.PowerState
      WScript.Echo "PowerSupplyState: " & objItem.PowerSupplyState
      WScript.Echo "PrimaryOwnerContact: " & objItem.PrimaryOwnerContact
      WScript.Echo "PrimaryOwnerName: " & objItem.PrimaryOwnerName
      WScript.Echo "ResetCapability: " & objItem.ResetCapability
      WScript.Echo "ResetCount: " & objItem.ResetCount
      WScript.Echo "ResetLimit: " & objItem.ResetLimit
      strRoles = Join(objItem.Roles, ",")
         WScript.Echo "Roles: " & strRoles
      WScript.Echo "Status: " & objItem.Status
      strSupportContactDescription = Join(objItem.SupportContactDescription, ",")
         WScript.Echo "SupportContactDescription: " & strSupportContactDescription
      WScript.Echo "SystemStartupDelay: " & objItem.SystemStartupDelay
      strSystemStartupOptions = Join(objItem.SystemStartupOptions, ",")
         WScript.Echo "SystemStartupOptions: " & strSystemStartupOptions
      WScript.Echo "SystemStartupSetting: " & objItem.SystemStartupSetting
      WScript.Echo "SystemType: " & objItem.SystemType
      WScript.Echo "ThermalState: " & objItem.ThermalState
      WScript.Echo "TotalPhysicalMemory: " & objItem.TotalPhysicalMemory
      WScript.Echo "UserName: " & objItem.UserName
      WScript.Echo "WakeUpType: " & objItem.WakeUpType
      WScript.Echo
   Next
Next


Function WMIDateStringToDate(dtmDate)
WScript.Echo dtm:
	WMIDateStringToDate = CDate(Mid(dtmDate, 5, 2) & "/" & _
	Mid(dtmDate, 7, 2) & "/" & Left(dtmDate, 4) _
	& " " & Mid (dtmDate, 9, 2) & ":" & Mid(dtmDate, 11, 2) & ":" & Mid(dtmDate,13, 2))
End Function
Speichern als *.vbs

Diese "kleine" Script dient dazu verschiedene Informationen auszulesen.
All diese Informationen werden zum Teil aus der Registrierung oder sonstigen Ressourcen des PC's ausgelesen.

Zunächst wird eine Verbindung zum Namespace hergestellt:
Code:
   Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Und dann wird die Klasse ausgewählt aus der die Informationen gelesen werden sollen:
Code:
   Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem", "WQL", _
                                          wbemFlagReturnImmediately + wbemFlagForwardOnly)
Mit dem WMI Scriptomatic 2.0 kann man sich hierzu alle vorhandenen Namespaces auflisten lassen und alle dazugehörigen Klassen.
Der CIMV2 ist der meistbenutzte Namespace in dem auch alle wichtigen Klassen gespeichert sind.

Zum Thema MOF:
Ich bin auf die Idee gekommen eine eigene MOF zu schreiben, da ich (siehe anderes TUT von mir) leider feststellen musste, dass egal wie mächtig WMI auch ist es ein Problem hat.

Wenn der derzeit angemeldete Benutzer von dem Client, von dem man die Informationen auslesen möchte nur Benutzerrechte hat werden diverse Dinge nicht ausgelesen.
Leider ist mir keine Lösung bekannt und anderen ist wohl ebenfalls noch keine Lösung eingefallen!

Also dachte ich mir: Warum les ich nicht den Wert direkt aus der Registrierung?
In meinem speziellen Fall war es der derzeit eingeloggte User.

Vorraussetzung: Der Registrierungsschlüssel muss auf allen PC's die man auslesen möchte gleich sein.
Sprich z.b. Software die auf einem PC vorhanden ist und auf dem anderen nicht wird nicht gehen.

Kommen wir gleich auf den Punkt wie diese MOF auszusehen hat:

Code:
qualifier dynamic:ToInstance;
qualifier ProviderClsid:ToInstance;
qualifier ClassContext:ToInstance;
qualifier propertycontext:ToInstance;
 [dynamic, provider("RegProv"),
ProviderClsid("{fe9af5c0-d3b6-11ce-a5b6-00aa00680c3f}"),
ClassContext
("local|HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion")
]
class LoggedUsername {
   [key] string KeyName;
   [read, propertycontext("DefaultUserName")]      string DefaultUserName;
};
Speichern unter *.mof



Wichtig für eigenständige Änderungen ist nur der Registrierungsschlüssel.
Zu beachten ist, dass IMMER das local vorne stehen bleibt und nicht evtl. PC1.
Dies geht natürlich auch, aber dann kann immer nur der angegebene Schlüssel von PC1 ausgelesen werden.
Desweiteren ist zu beachten, dass es immer "\\" sein müssen.
Nächster Punkt ist der Schlüssel an sich. Dieser Schlüssel darf nicht bis zum letzten Tree kopiert werden sondern den nächsthöheren. Wenn man sich den obigen Schlüssel mal in der Registrierung ansieht wird man festellten, dass dieser keine eigenen Attribute hat. Der "DefaultUserName" steht im Schlüssel WinLogon.
Der Klasse muss natürlich ein anderer Name gegeben werden, damit diese hinzugefügt werden kann ohne die andere, falls vorhandene, Klasse zu überschreiben.

Code:
   [read, propertycontext("DefaultUserName")]      string DefaultUserName;
Hiermit gebt ihr an welchen Wert ihr aus dem genannten Schlüssel auslesen wollt.
In dem Fall ist es DefaultuserName. Das ist der Wert in den Klammern. "string DefaultUserName" ist der Wert, der in den WMI Namespace eingetragen wird.
In diesem Fall wollen wir nur lesen -> read!

Zum mitmachen gehen wir nun in die CMD und wechseln in das Verzeichnis in dem die MOF Datei liegt.

Nun schreiben mir "mofcomp -check DATEINAME.mof"
Hiermit wird der Syntax überprüft (der hier nun korrekt sein sollte).
Anschließend wird nun nur "mofcomp DATEINAME.mof" eingeben und die neue Klasse wird dem DefaultNamespace hinzugefügt.
Sprich die klasse landet nicht in root\CIMV2 sondern in root\DEFAULT!

WICHTIG: Das muss auf allen PC's passieren, auf denen diese Klasse ausgelesen werden soll! Dies lässt sich per Batch oder aber, mit win32_prozess:createprocess realisieren!

Zum Auslesen benutzen wir folgendes Script:
Code:
strComputer = "."
Set WMI = GetObject("winmgmts:\\" & strComputer & _
    "\root\default")
Set colItems = WMI.ExecQuery("Select * from LoggedUsername")
For Each objItem In colItems
    WScript.Echo "DisplayName: "  & objItem.DefaultUserName
    WScript.Echo "KeyName: " & objItem.KeyName
Next
Speichern unter *.vbs


Als Ausgabe bekommt ihr nun zum einen den eingeloggten Benutzer und anschließend den Key in dem dieser Wert steht (Winlogon)

Was bringt das alles? Ich weiß doch wer gerade an diesem PC sitzt.
Natürlich kann man das ganze so erweitern, dass man den Benutzer des RemotePC's auslesen kann.

Hier der Code:
Code:
Const WbemAuthenticationLevelPktPrivacy = 6
strUser = InputBox("Please enter the user name: ")
strPassword = InputBox ("Please enter the Passwort: ")
strComputer = InputBox ("Please enter the Computername: ")
strNamespace = "root\default"

'Verbindung zum WMI Namespace herstellen================
Set objWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objWMIService = objwbemLocator.ConnectServer (strComputer, strNamespace, strUser, strPassword)
objWMIService.Security_.authenticationLevel = WbemAuthenticationLevelPktPrivacy


'Set objWMIService = GetObject("winmgmts:\\{impersonationLevel=impersonate}!\\" & strComputer & "\root\default")
Set colItems = objWMIService.ExecQuery("Select * from LoggedUsername")
For Each objItem In colItems
    WScript.Echo "DisplayName: "  & objItem.DefaultUserName
    WScript.Echo "KeyName: " & objItem.KeyName
Next
Speichern unter *.vbs

In dem Fall werden zunächst 3 Abfragen getätigt und anschließend die Verbindung zum RemoteComputerNamespace hergestellt.
Hierzu benötigt ihr natürlich administrative Rechte!
Der User kann (falls nötig) auch als DOMÄNE\ADMIN eingegeben werden bzw. muss wenn sich der RemotePC in einer anderen Domäne befindet als der eigene.

Soooo
Genug davon
Bei Fragen fragen

So far
Xaero
 
Zuletzt bearbeitet:
Oben