scarydaniel
Goto Top

Eventlog mittels VBScript auslesen

Hallo an alle! (=

Ich befasse mich gerade neu mit VBS und bin daher vorerst auf eure Unterstützung angewiesen. (=

Ich benötige ein VBScript welches mir Rückgabewerte aus dem Windows-Eventlog für
- die Anzahl der Fehler und Warnungen für den aktuellen
- die Anzahl der Gesamtfehler und -warnungen
- sowie den Text des letzten Fehlers bzw. Warnung
liefert.

Müsste unter Windows Server 2003 und 2008 lauffähig sein.

Soweit bin ich schon mal:

'VBScript

strComputer = "." 'Den aktuellen Computer durchsuchen
Set objWMIService = GetObject("winmgmts:" & "\\" & "localhost" & "\root\cimv2") 'WMI zum durchsuchen nutzen


'Auslesen der Nachricht der letzten Warnung bzw. des letzten Fehlers

Set letztesEvent = objWMIService.ExecQuery _
("Select * from Win32_NTLogEvent where (EventType = '1' OR EventType = '2')") 'Abfrage aller Ereignisse aus der Ereignisanzeige mit dem Eventtyp 1 (Fehler) und 2 (Warnung)

For Each objEvent In letztesEvent
letzte_Nachricht = objEvent.Message 'Schleife ??? etc.
Next


'Auslesen der Anzahl und Warnungen des aktuellen Tags

Set FehlerWarnungenTag = objWMIService.ExecQuery _
("Select * from Win32_NTLogEvent where (EventType = '2' OR EventType = '2') and where TimeWritten.Date = ' '") 'Abfrage aller Ereignisse aus der Ereignisanzeige mit dem Eventtyp 1 (Fehler) und 2 (Warnung)
Anzahl_Events_Tag = FehlerWarnungenTag.Count


'Auslesen der Anzahl und Warnungen (gesamt)

Set FehlerWarnungenGesamt = objWMIService.ExecQuery _
("Select * from Win32_NTLogEvent where (EventType = '3' OR EventType = '2')") 'Abfrage aller Ereignisse aus der Ereignisanzeige mit dem Eventtyp 1 (Fehler) und 2 (Warnung)
Anzahl_Events_Gesamt = FehlerWarnungenGesamt.Count


'Anzeige der Werte in einer Windows-Box (optional)

wscript.echo "Letzte Nachricht: " & letzte_Nachricht & vbLf & "Anzahl Fehler/Warnungen heute: " & Anzahl_Events_Tag & vbLf & "Anzahl Fehler/Warnungen Gesamt: " & Anzahl_Events_Gesamt


'Werte in vorhandene Textdatei schreiben (optional)

Set ZugriffDatei = CreateObject("Scripting.FileSystemObject") 'Erzeugen eines Objekts für den Zugriff auf das Dateisystem
Set Datei = ZugriffDatei.OpenTextFile("E:\dd.txt",2,True) 'Mit dem erzeugten Objekt Textdatei E:\dd.txt im Schreibmodus (2) öffnen bzw. erstellen wenn nicht vorhanden (True)

Datei.writeLine "Nachricht der letzten Warnung bzw. des letzten Fehlers: " & letzte_Nachricht
Datei.writeLine "Anzahl und Warnungen des aktuellen Tags: " & Anzahl_Events_Tag
Datei.writeLine "Anzahl und Warnungen (gesamt): " & Anzahl_Events_Gesamt

Datei.close 'E:\dd.txt schließen


Wie kann ich die Abfrage für die Anzahl der Fehler/Warnungen pro Tag so anpassen, dass diese stimmt?
Und was genau bedeutet "Set objWMIService = GetObject("winmgmts:" & "\\" & "localhost" & "\root\cimv2")" und "Set letztesEvent = objWMIService.ExecQuery _"

Danke! (=


PS: Nicht schlecht für das erste VBScript oder? (=

Content-Key: 170675

Url: https://administrator.de/contentid/170675

Printed on: April 19, 2024 at 01:04 o'clock

Member: Friemler
Friemler Jul 30, 2011 at 22:49:40 (UTC)
Goto Top
Hallo ScaryDaniel,

Zitat von @ScaryDaniel:
PS: Nicht schlecht für das erste VBScript oder?
hm na ja, Copy&Paste machen noch keinen Scripter...


Hier mal eine Version, die auch das Problem der Anzahl Fehler/Warnungen des aktuellen Tages löst:
 'Den aktuellen Computer durchsuchen  
strComputer          = "."  

'Objekt für den Zugriff auf WMI erzeugen, das mit dem Namespace CIMV2 verbunden ist  
Set objWMIService    = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")  
Set objSWbemDateTime = CreateObject("WbemScripting.SWbemDateTime")  


'Abfrage aller Ereignisse aus der Ereignisanzeige mit dem Eventtyp 1 (Fehler) und 2 (Warnung)  
Set colAllEvents = objWMIService.ExecQuery("SELECT * FROM Win32_NTLogEvent " & _  
                                           "WHERE (EventType = '1' OR EventType = '2')" _  
                                          )

'Auslesen der Nachricht der letzten Warnung bzw. des letzten Fehlers  
'Dabei LF durch CR+LF ersetzen  
For Each objEvent In colAllEvents
  strLastMessage = Replace(objEvent.Message, vbLf, vbCrLf)
  Exit For
Next

'Ermitteln der Anzahl Fehler und Warnungen gesamt  
intAllEventsCnt = colAllEvents.Count


'Abfrage aller Ereignisse aus der Ereignisanzeige mit dem Eventtyp 1 (Fehler) und 2 (Warnung) vom aktuellen Tag  
objSWbemDateTime.SetVarDate CDate(Date), True

Set colEventsToday = objWMIService.ExecQuery("SELECT * FROM Win32_NTLogEvent " & _  
                                             "WHERE ((EventType = '1' OR EventType = '2') " & _  
                                                    "AND " & _  
                                                    "(TimeWritten >= '" & objSWbemDateTime.Value & "')" & _  
                                                   ")" _  
                                            )

'Ermitteln der Anzahl Fehler und Warnungen des aktuellen Tags  
intTodayEventsCnt = colEventsToday.Count


'Anzeige der Werte in einer Windows-Box (optional)  
WScript.Echo "Letzte Nachricht:"                & vbCrLf & vbCrLf & strLastMessage & vbCrLf & _  
             "Anzahl Fehler/Warnungen heute : " & intTodayEventsCnt & vbCrLf & _  
             "Anzahl Fehler/Warnungen gesamt: " & intAllEventsCnt  


'Werte in vorhandene Textdatei schreiben (optional)  
'Erzeugen eines Objekts für den Zugriff auf das Dateisystem  
Set objFSO = CreateObject("Scripting.FileSystemObject")  

'Mit dem erzeugten Objekt Textdatei E:\dd.txt erstellen  
'Wenn schon vorhanden, dann überschreiben (True)  
Set objOutFile = objFSO.CreateTextFile("E:\dd.txt", True)  

objOutFile.Write     "Nachricht der letzten Warnung/des letzten Fehlers:"  & vbCrLf & vbCrLf & strLastMessage & vbCrLf  
objOutFile.WriteLine "Anzahl Warnungen und Fehler heute : "                & intTodayEventsCnt  
objOutFile.WriteLine "Anzahl Warnungen und Fehler gesamt: "                & intAllEventsCnt  

objOutFile.Close

Schlüssel für die Lösung war hier die Verwendung der SWbemDateTime-Klasse, die die Konvertierung des Datums in ein für WQL-Queries (WQL=WMI Query Language) geeignetes Format besorgt.

Wie Du evtl. von anderen Programmiersprachen schon weißt, sind Datums- und Zeitwerte intern vom Typ LongInteger (UNIX- bzw. C-Time, Anzahl Sekunden seit dem 1. Januar 1970 00:00 Uhr) oder Float (ein Tag wird in 86400 Sekunden zerlegt, Millisekunden sind dann Bruchteile von 1/86400, Startpunkt der Zählung ist z.B. 01.01.1900 00:00:00 Uhr o.ä.).

Wenn man also z.B. den Datumswert 31.07.2011 ins WMI-Format konvertieren lässt, wird daraus zunächst mal ein String in einem für WQL-Queries zulässigen Format, der intern von WMI in einen Zahlenwert gewandelt wird, der dem 31.07.2011 00:00:00 Uhr entspricht. Will man alle Ereignisse von heute erhalten, muss man deshalb TimeWritten und objSWbemDateTime.Value mit >= vergleichen, der Operator = würde nur Ereignisse von 00:00:00 Uhr liefern.

Wenn man z.B. alle Ereignisse vom 01.05.2010 erhalten will, benötigt man zwei Instanzen der Klasse SWbemDateTime. Eines mit dem man den Datumswert 01.05.2010 konvertiert und eines mit dem man den Datumswert 02.05.2010 konvertiert. Dann vergleicht man folgendermaßen:
Set objSWbemDateTime0105 = CreateObject("WbemScripting.SWbemDateTime")  
Set objSWbemDateTime0205 = CreateObject("WbemScripting.SWbemDateTime")  

objSWbemDateTime0105.SetVarDate CDate("01.05.2010"), True  
objSWbemDateTime0205.SetVarDate CDate("02.05.2010"), True  

Set colEventsToday = objWMIService.ExecQuery("SELECT * FROM Win32_NTLogEvent " & _  
                                             "WHERE ((EventType = '1' OR EventType = '2') " & _  
                                                    "AND " & _  
                                                    "(TimeWritten >= '" & objSWbemDateTime0105.Value & "' " & _  
                                                     "AND " & _  
                                                     "TimeWritten < '" & objSWbemDateTime0205.Value & "'" & _  
                                                    ")" & _  
                                                   ")" _  
                                            )

Das Thema WMI und WMI-Klassen ist zu komplex, um hier eine befriedigende Erklärung abgeben zu können. Ich poste einfach mal ein paar Links, durch die (und noch viele mehr) Du Dich durchackern musst. Englisch sollte man so einigermaßen beherrschen.

http://msdn.microsoft.com/en-us/library/aa393687%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/aa389763%28v=VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/aa392902%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/aa394606%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/aa394605%28v=vs.85%29.aspx
http://technet.microsoft.com/de-de/magazine/2006.07.scriptingguy%28en-u ...
http://msdn.microsoft.com/en-us/library/aa384642%28v=VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/aa394553%28v=VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/aa394572%28v=VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/aa394084%28v=VS.85%29.aspx

Gruß
Friemler
Member: rubberman
rubberman Jul 31, 2011 at 13:15:38 (UTC)
Goto Top
Hallo Zusammen und willkommen im Forum ScaryDaniel!

Ergänzend zu Friemlers Ausführungen:

Im Allgemeinen reicht ein SWbemDateTime Object:
Set objSWbemDateTime = CreateObject("WbemScripting.SWbemDateTime")  

objSWbemDateTime.SetVarDate DateSerial(2010, 5, 1), True
strSWbemDateTime1 = objSWbemDateTime.Value
objSWbemDateTime.Day = 2
strSWbemDateTime2 = objSWbemDateTime.Value

WScript.Echo strSWbemDateTime1 & "; " & strSWbemDateTime2  
... aber das nur am Rande.

Wenn es um WMI geht, hat mir die ScriptomaticV2.hta schon gute Dienste geleistet. Damit kann man automatisch Scriptcode erzeugen und Änderungen testen.
Bei aktivem UAC (Vista, Win7) muss man diese allerdings als Admin rennen lassen. Dazu habe ich mir diesen Batch geschrieben, der per Rechsklick > "Als Administrator ausführen" die HTA mit entsprechenden Rechten startet:
@echo off &setlocal

:: Prüfen, ob der Batch mit administrativen Rechten gestartet wurde.
fsutil fsinfo drives|findstr /c:":\\">nul ||(  
  echo Run as Admin!
  pause>nul
  goto :eof
)

:: Sorgt dafür, dass temporäre Script-Dateien in %temp% angelegt werden.
cd /d "%temp%"  

:: Scriptomatic mit hoher Priorität starten
start "" /realtime "%SystemRoot%\system32\mshta.exe" "%~dp0ScriptomaticV2.hta"  

Grüße
rubberman
Member: ScaryDaniel
ScaryDaniel Jul 31, 2011 at 15:33:39 (UTC)
Goto Top
Hallo und danke für die Antworten! (=

Allerdings glaube ich kaum, dass mich ein Copy&Paste á la Guttenberg hier sinnvoll ans Ziel geführt hätte.
Logo hab ich den ganzen Tag gegoogelt. Aber ich hab mir das Script dann alleine zusammengestellt UND auch verstanden was da vor sich geht.
Und daher finde ich, dass das ne gute Leistung war! (-;

Ich habe den Teil mit der Anzahl pro Tag jetzt in mein Script reingebaselt, funktioniert super, vielen vielen Dank!

Allerdings habe ich noch ein paar Fragen:
"objSWbemDateTime.SetVarDate CDate(Date), True" generiert ja das aktuelle Datum im passenden WMI-Format, aber welcher Wert (CDDate, Date, True) bedeutet genau was?
"winmgmts:\\" & strComputer & "\root\cimv2" --> winmgmts.exe ist mir denk ich bekannt, aber warum winmgmts:\\? strComputer ist klar. Was hat es noch mit dem Namespace auf sich?
Und warum wird bei der Abfrage nach der letzten Nachricht auch wirklich die letzte Nachricht genommen, obwohl dieses gar nicht explizit angegeben ist? Es werde ja alle Events abgerufen, wird automatisch das aktuelles zuerst genommen? Dann würde ich es verstehen. (=
Bei meinem Script werden nur die Windows Protokolle abgefragt, bei Fremlier allerdings auch die Anwendungs - und Dienstprotokolle habe ich festgestellt. Ich sehe aber keinen Unterschied in den Scripten, der dies hervorruft!?

Hier mein Script:
 
'VBScript  


'Erzeugen eines Objekts, das mit dem Namespace CIMV2 verbunden ist, für den Zugriff auf WMI zum durchsuchen des lokalen PCs   
Set ZugriffWMI = GetObject ("winmgmts:\\" & "localhost" & "\root\cimv2")   


'Erzeugen eines Objekts zur Zeit-/Datumsbearbeitung und anschließendes generieren des aktuellen  
'Datums im passenden Format für WMI (wie TimeWrtitten z. B. 20110731000000.000000+120)  
Set Zeit = CreateObject("WbemScripting.SWbemDateTime")  
Zeit.SetVarDate CDate(Date), True
Zeit_test1 = Zeit.Value

'Abfrage aller Fehler (Eventtyp 1) und Warnungen (Eventtyp 2) aus der Ereignisanzeige des aktuellen  
'Tages (mithilfe von TimeWrtitten und dem generierten Datum) und anschließendes speichern der Anzahl  
Set FehlerWarnungenGesamt = ZugriffWMI.ExecQuery _
("SELECT * FROM Win32_NTLogEvent WHERE (EventType = '3' OR EventType = '3') AND (TimeWritten >= '" & Zeit & "')")  
	Anzahl_Tag = FehlerWarnungenGesamt.Count


'Abfrage aller Fehler (Eventtyp 1) und Warnungen (Eventtyp 2) aus der Ereignisanzeige  
'und anschließendes speichern der Anzahl  
Set FehlerWarnungenTag = ZugriffWMI.ExecQuery _
("Select * from Win32_NTLogEvent WHERE (EventType = '3' OR EventType = '2')")  
	Anzahl_Gesamt  = FehlerWarnungenTag.Count


'Abfrage aller Ereignisse aus der Ereignisanzeige mit dem Eventtyp 1 (Fehler) und 2 (Warnung) und mithilfe einer  
'For-Each-Next-Schleife das erste Ereignis (ist automatisch das aktuellste) speichern  
Set letztesEvent = ZugriffWMI.ExecQuery ("SELECT * FROM Win32_NTLogEvent WHERE (EventType = '3' OR EventType = '3')")   
	For Each objEvent In letztesEvent
	    letzte_Nachricht = objEvent.Message
	Next


'geforderte Rückgabewerte:  
'Anzahl der Fehler/Warnungen pro Tag --> Anzahl_Tag  
'Anzahl der Gesamtfehler/Warnungen   --> Anzahl_Gesamt  
'Text des letzten Fehlers/Warnung    --> letzte_Nachricht  


'Anzeige der Werte in einer Windows-Box (optional)  

wscript.echo 	"Anzahl Fehler/Warnungen heute: "   & Anzahl_Tag 	& VbLf & _  
		"Anzahl Fehler/Warnungen Gesamt: "  & Anzahl_Gesamt 	& VbLf & VbLf & _	  
		"Letzte Nachricht: "		    			& VbLf & _  
		letzte_Nachricht	

	     
'Werte in vorhandene Textdatei schreiben (optional)  

Set ZugriffDatei = CreateObject("Scripting.FileSystemObject")	'Erzeugen eines Objekts für den Zugriff auf das Dateisystem  
Set Datei = ZugriffDatei.OpenTextFile("E:\dd.txt",2,True) 	'Textdatei im Schreibmodus (2) öffnen bzw. erstellen wenn nicht vorhanden (True)  

 Datei.writeLine "Anzahl und Warnungen des aktuellen Tags: " & Anzahl_Tag  
 Datei.writeLine "Anzahl und Warnungen (gesamt): " & Anzahl_Gesamt  
 Datei.writeLine 'Leerzeile  
 Datei.writeLine "Nachricht der letzten Warnung bzw. des letzten Fehlers: "  
 Datei.writeLine letzte_Nachricht

Datei.close 'E:\dd.txt schließen  
Member: rubberman
rubberman Jul 31, 2011 at 20:15:55 (UTC)
Goto Top
Hallo ScaryDaniel.

Zitat von @ScaryDaniel:
"objSWbemDateTime.SetVarDate CDate(Date), True" generiert ja das aktuelle Datum im passenden WMI-Format, aber welcher Wert (CDDate, Date, True) bedeutet genau was?

Die Date Funktion gibt das derzeitige Datum zurück.
CDate würde einen String in einen Datumswert umwandeln. Diese Funktion ist an der Stelle unnötig, da Date schon einen Wert im richtigen Format liefert.
Das "True" gehört zur SetVarDate Methode und spezifiziert, dass die lokale Zeiteinstellung zugrunde gelegt wird.

Zitat von @ScaryDaniel:
"winmgmts:\\" & strComputer & "\root\cimv2" --> winmgmts.exe ist mir denk ich bekannt, aber warum winmgmts:\\? strComputer ist klar. Was hat es noch mit dem Namespace auf sich?

Das ist schlicht und einfach die entsprechende Syntax, die benötigt wird um mit der GetObject Funktion das richtige Objekt zu referenzieren.

Zitat von @ScaryDaniel:
Und warum wird bei der Abfrage nach der letzten Nachricht auch wirklich die letzte Nachricht genommen, obwohl dieses gar nicht explizit angegeben ist? Es werde ja alle Events abgerufen, wird automatisch das aktuelles zuerst genommen? Dann würde ich es verstehen. (=

Es wird eine Sammlung von Events zurückgegeben, deren Elemente in chronologisch umgekehrter Reihenfolge kommen (das jüngste zuerst).

Zitat von @ScaryDaniel:
Bei meinem Script werden nur die Windows Protokolle abgefragt, bei Fremlier allerdings auch die Anwendungs - und Dienstprotokolle habe ich festgestellt. Ich sehe aber keinen Unterschied in den Scripten, der dies hervorruft!?

Keine Ahnung. Ihr fragt unterschiedlich Eventtypen ab. Hast du verifiziert, ob es entsprechende Events für die von dir abgefragten Typen gibt?

Grüße
rubberman

PS: Für alle von mir kursiv gesetzten Funktionen und Methoden findest du eine Referenz im MSDN.