11234
Goto Top

Ereignisanzeige auslesen und in *.txt-Datei schreiben

Hi,

ich möchte ein VBSkript haben, welches die Ereignisanzeige ausließt und anschließend in eine Textdatei schreibt. Leider habe ich nirgends Beispiel dafür gefunden und einen Ansatz dazu ist mir bisher auch fern geblieben ;)

Wäre super wenn ihr mir helfen könntet.

Mir freundlichen Grüßen

Content-Key: 28805

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

Printed on: April 16, 2024 at 21:04 o'clock

Mitglied: 27119
27119 Mar 23, 2006 at 12:04:52 (UTC)
Goto Top
Member: djbrandt
djbrandt Mar 23, 2006 at 20:59:22 (UTC)
Goto Top
Hi, da gibt es von M$ ein Tool:

dumpel.exe


http://www.microsoft.com/windows2000/techinfo/reskit/tools/existing/dum ...

Grüße

Dieter
Mitglied: 11234
11234 Mar 24, 2006 at 10:32:27 (UTC)
Goto Top
Hallo,

erstmal danke. Allerdings brauche ich keine Tools oder ähnliches, sondern es sollte wirklich ein Skript sein.

Mittlerweile habe ich allerdings eine Lösung dafür gefunden. Trotzdem nochmal vielen Dank ;)
Member: misterdemeanor
misterdemeanor Apr 05, 2006 at 10:08:44 (UTC)
Goto Top
Die da wäre?
Es wäre sehr nett von Dir wenn Du es hier noch postest.

Grüße
Mitglied: 11234
11234 Apr 10, 2006 at 13:00:31 (UTC)
Goto Top
Natürlich, dass ist kein Problem.

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

Set colLoggedEvents = objWMIService.ExecQuery ("Select * from Win32_NTLogEvent Where Logfile = 'Application'")  

For Each objEvent In colLoggedEvents
    WScript.Echo "Category: " & objEvent.Category  
    WScript.Echo "Computer Name: " & objEvent.ComputerName  
    WScript.Echo "Event Code: " & objEvent.EventCode  
    WScript.Echo "Message: " & objEvent.Message  
    WScript.Echo "Record Number: " & objEvent.RecordNumber  
    WScript.Echo "Source Name: " & objEvent.SourceName  
    WScript.Echo "Time Written: " & objEvent.TimeWritten  
    WScript.Echo "Event Type: " & objEvent.Type  
    WScript.Echo "User: " & objEvent.User  
Next

Über die Konsole führst du das Skript nun folgendermaßen aus: cscript datei.vbs > ausgabe.txt


Derweil tut sich mir ein anderes Problem auf. Ich hab ein Array welches ich vorher definiere in dem bestimmte Eventtypen stehen die ich NICHT mit auslesen möchte. Zum Beispiel Filter("Warnungen", "Informationen") ... logischerweise denkt man sich nun das die SQL Anweisung dafür folgendermaßen aussehen sollte:

Select * from Win32_NTLogEvent Where Logfile = 'Application' WHERE EventType <> Filter(i)

Doch darauf bekomme ich nur folgenden Fehlertext: 0x80041017
Wenn mir jemand dabei behilflich sein könnte das ich dieses Problem auf die Art und Weise (mit einem Array) lösen kann, dann wäre ich dafür sehr dankbar!
Member: misterdemeanor
misterdemeanor Apr 10, 2006 at 14:04:32 (UTC)
Goto Top
Grüß Dich Felix, (alddA Namensvetter *gg*)

Du verwendest ja bereits die richtige Klasse, also ein Blick auf die EventType-Eigenschaft und Dein Problem ist gelöst :

'Auszug aus dem MSDN (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk ..)

EventType
Data type: uint8
Access type: Read-only

Windows Server 2003, Windows 2000, and Windows XP: Type of event.

Value Meaning
1 Error
2 Warning
3 Information
4 Security audit success
5 Security audit failure

Dieser Code hat bei mir einwandfrei (in VBA) funktioniert:

Public Function xxx()
  Dim strComputer As String
  Dim objWMIService As Object
  Dim colLoggedEvents As Object
  Dim objEvent As Object
  Dim i As Integer
  Dim FILTERED As Boolean
  
  Dim DeinArrayMitEventTypeIntegers(0 To 1) As Integer
    DeinArrayMitEventTypeIntegers(0) = 3
    DeinArrayMitEventTypeIntegers(1) = 2

    strComputer = "."  
    Set objWMIService = GetObject("winmgmts:" & "\\" & strComputer & "\root\cimv2")  
    
    Set colLoggedEvents = objWMIService.ExecQuery("Select * from Win32_NTLogEvent Where Logfile = 'Application'")  
    
    For Each objEvent In colLoggedEvents
      For i = LBound(DeinArrayMitEventTypeIntegers) To UBound(DeinArrayMitEventTypeIntegers)
        If (objEvent.EventType = DeinArrayMitEventTypeIntegers(i)) Then FILTERED = True
      Next i
      If Not FILTERED Then
        Debug.Print "Category: " & objEvent.Category  
        Debug.Print "Computer Name: " & objEvent.ComputerName  
        Debug.Print "Event Code: " & objEvent.EventCode  
        Debug.Print "Message: " & objEvent.Message  
        Debug.Print "Record Number: " & objEvent.RecordNumber  
        Debug.Print "Source Name: " & objEvent.SourceName  
        Debug.Print "Time Written: " & objEvent.TimeWritten  
        Debug.Print "Event Type: " & objEvent.Type  
        Debug.Print "User: " & objEvent.User  
      End If
      FILTERED = False
    Next objEvent
End Function

Wie und wo Du Deinem Array die Werte zuweist hängt natürlich von Dir ab.

Und bitte nicht irgendwie /angemacht/ fühlen. Wenn jemand Mal ein gleiches Problem hat und diesen Post hier ohne Lösung liest...
War ja auch keineswegs böse gemeint, oder so.

Auf jeden Fall hoffe ich das Dir das hier hilft.

Grüße
Felix
Mitglied: 11234
11234 Apr 10, 2006 at 14:25:19 (UTC)
Goto Top
Hi Felix ;o)

Erstmal danke für die schnelle Antwort.

Allerdings besteht da ein Problem. Ich kann mit VBA nix anfangen sondern das es soll alles unter Visual Basic Script (VBS) entwickelt werden. Damit fallen so einige standardmäßige Sachen die bei VBA möglich sind leider schonmal raus, da sie nicht verfügbar sind.

Desweiteren wird das Filterarray später dynamisch befüllt, es sollen also beliebig viele Filter möglich sein, da der User diese über eine GUI selbst definieren kann (klar werden das nicht mehr als die von dir genannten 5 sein, würde auch kein Sinn machen). Die Filter werden später aus einer XML-Datei gelesen und das Array anschließend dementsprechend befüllt.

Ich hoffe mal das ich mich jetzt vielleicht etwas verständlicher ausgedrückt habe, denn die Lösung funktioniert so nicht ganz für die eigentliche Problemstellung. Trotzdem natürlich ein großes Dankeschön :o)
Member: misterdemeanor
misterdemeanor Apr 10, 2006 at 15:14:49 (UTC)
Goto Top
So,
habe mich Mal ein bischen mit VBScript beschäftigt. Ist mir ja auch peinlich das ich das vorher noch nie gemacht hab...

Das sollte eigtl geeignet sein. Du müßtest halt noch evtl näher beschreiben wie die Daten in der XML-File gespeichert werden, und wie Du die auslesen willst um das Array zu befüllen. Also ich sehe da keine großen Probleme...

Hier mal die .VBS - File die ich zusammengeschreibselt hab. Habe ich mit Windows-Editor getippt und zu "tode geärgert" *aargh*

  Dim DeinArrayMitEventTypeIntegers(1)
    DeinArrayMitEventTypeIntegers(0) = 1
    DeinArrayMitEventTypeIntegers(1) = 1

Call outputEventsToFile("C:\Test.txt","Application",DeinArrayMitEventTypeIntegers)  

Public Sub outputEventsToFile(ByVal filename,ByVal LogFileType,ByVal filteredEvents())
On Error Resume Next
  Dim strComputer 
  Dim objWMIService 
  Dim colLoggedEvents 
  Dim objEvent 
  Dim i 
  Dim FILTERED
  Dim fso, f
  Set fso = CreateObject("Scripting.FileSystemObject")  
  Set f = fso.OpenTextFile(filename, 2, True)  

    strComputer = "."  
    Set objWMIService = GetObject("winmgmts:" & "\\" & strComputer & "\root\cimv2")      
    Set colLoggedEvents = objWMIService.ExecQuery("Select * from Win32_NTLogEvent Where Logfile = '" & LogFileType & "'")  
    
    For Each objEvent In colLoggedEvents
      For i = LBound(DeinArrayMitEventTypeIntegers) To UBound(DeinArrayMitEventTypeIntegers)
        If (objEvent.EventType = DeinArrayMitEventTypeIntegers(i)) Then
          FILTERED = True
          Exit For
        End If
      Next 

      If Not FILTERED Then
        f.WriteLine( "Category: " & objEvent.Category)  
        f.WriteLine "Computer Name: " & objEvent.ComputerName  
        f.WriteLine "Event Code: " & objEvent.EventCode  
        f.WriteLine "Message: " & objEvent.Message  
        f.WriteLine "Record Number: " & objEvent.RecordNumber  
        f.WriteLine "Source Name: " & objEvent.SourceName  
        f.WriteLine "Time Written: " & objEvent.TimeWritten  
        f.WriteLine "Event Type: " & objEvent.Type  
        f.WriteLine "User: " & objEvent.User  
      End If
      FILTERED = False
    Next
    f.Close
End Sub
Member: Biber
Biber Apr 10, 2006 at 16:25:00 (UTC)
Goto Top
Na, Ihr Felixe,

@misterdemeanor,

ich glaube, Deine Lösung geht ein wenig an der eigentlichen "kleinen" Frage vorbei.
Und außerdem sollte ja IMHO ein Ziel sein, schon im SELECT-String möglichst die Menge an Daten einzuschränken/zu filtern und nicht immer das ganze Eriegnisprotokoll zu holen und danach zu entscheiden, ob einzelne Sätze für Anzeige oder Ausdruck unterdrückt werden.

@11234
Du hast einen "falschen" SQL-String zusammengebastelt, da Du Strings im String hast. Das ist alles.

ALT:
"Select * from Win32_NTLogEvent Where Logfile = 'Application' WHERE EventType <> Filter(i)"

NEU:
"Select * from Win32_NTLogEvent Where Logfile = 'Application' WHERE EventType <> ' " & Filter(i) & " ' "

Oder, mal im Zusammenhang im Schnipsel:

CONST EVENTTYPE_ERROR             = "1"  
CONST EVENTTYPE_WARNING           = "2"  
CONST EVENTTYPE_INFORMATION       = "3"  
CONST EVENTTYPE_SUCCESSAUDIT      = "4"  
CONST EVENTTYPE_FAILUREAUDIT      = "5"  

strComputer = "."  
arrEventType = array( EVENTTYPE_ERROR, EVENTTYPE_WARNING , EVENTTYPE_FAILUREAUDIT)
Set objWMIService = GetObject("winmgmts:" & "\\" & strComputer & "\root\cimv2")  
strSelect = "Select * from Win32_NTLogEvent Where Logfile = 'Application'"  
'--------------------> hier 4 Beispiele für das Zusammenbasteln des SELECT-Strings  
'--------------------> wahlweise auskommentieren  
' Set colLoggedEvents = objWMIService.ExecQuery (strSelect   & " AND EventType = '" & "1" & "' ")  
' Set colLoggedEvents = objWMIService.ExecQuery (strSelect   & " AND EventType = '" & EVENTTYPE_ERROR & "' ")  
' Set colLoggedEvents = objWMIService.ExecQuery (strSelect   & " AND EventType <> '" & EVENTTYPE_ERROR & "' ")  
Set colLoggedEvents = objWMIService.ExecQuery (strSelect   & " AND EventType = '" & arrEventType(1) & "' ")  
'Remember: arrEventType(1) == EVENTTYPE_WARNING   
For Each objEvent In colLoggedEvents
      WScript.Echo "Category: " & objEvent.Category  
      WScript.Echo "Computer Name: " & objEvent.ComputerName  
      WScript.Echo "Event Code: " & objEvent.EventCode  
      WScript.Echo "Message: " & objEvent.Message  
      WScript.Echo "Record Number: " & objEvent.RecordNumber  
      WScript.Echo "Source Name: " & objEvent.SourceName  
      WScript.Echo "Time Written: " & objEvent.TimeWritten  
      WScript.Echo "Event Type: " & objEvent.Type  
      WScript.Echo "User: " & objEvent.User  
Next
'P.S. VBS würde auch zulassen:  
'Set colLoggedEvents = objWMIService.ExecQuery (strSelect   & " AND EventType = '" & 1 & "' ")  
'.... also einen numerischen Wert in den String reinzudrücken...aber dieses "feature" wollte ich mir nicht angewöhnen.  
'  

Gruß
Biber
Member: misterdemeanor
misterdemeanor Apr 10, 2006 at 16:51:46 (UTC)
Goto Top
Hi Biber,
Na Dein Code sieht schon N bissel sauberer aus als meiner *g*

Aber auch wenn ich meist zu kompliziert und um die Ecke denke *kurzeDenkpause*
glaube ich das Felix *kurzeDenkpause* schon alle in seinem Array enthaltenen Eventtypen
ausschließen möchte.
Also glaube ich das doch eine Schleife von nöten ist in der die Eventtypen die er nicht
haben will ausschließt bzw. umgekehrt.
Das dann gleich in den WHERE String zu basteln wäre natürlich eine /bessere/ Lösung :

...
where = "Logfile='Application' "  

For i = LBound([array()]) To UBound([array()])
     If i <> UBound([array()]) Then
         where = where &  " AND EventType<>" & array(i)   
     End If
Next
...

Aber vielleicht hab ich Felix *kurzeDenkpause* auch nur einfach falsch verstanden.

Grüße
Felix *kopfkratz*
Member: Biber
Biber Apr 10, 2006 at 17:14:04 (UTC)
Goto Top
face-big-smile

Nein, hast ja schon im Ansatz Recht... (ich aber auch ..*gg)

Wo ich behaupte, Recht zu haben:
Sinnvoller ist es sicher, die Daten schon im SELECT-String einzuschränken.
Und nicht erst alles zu holen und dann nur einen oder zwei der EventTypes zu verwerten.

Wo Du Recht hast:
Klar, man/frau muss über die ganze Arraylänge wackeln und einen "AND"-String anhängen.
Wenn es denn nur ein Array-Element ist. Sonst gehts schief...
Denn wo Du noch danebenfasst:

Deine Bedingung wird ein leeres ResultSet zurückgeben, denn EventType kann ja nie vom Type "1" AND vom Type "2" AND vom Type "3" sein... face-wink

Da das doofe M$-WMI-Pseudo-SQL sowas nicht kann:
Where LogFile ='Application' AND Eventtype IN ('1', '2', '4')

...müsste eine ellenlange, aber korrekte zweite WHERE-Klausel so aussehen:

a) ALLE Arrayelemente
...Where LogFile='Application' AND ( EventType='1' OR EventType='2' OR EventType='4' )

b) KEINES der ArrayElemente:
...Where LogFile='Application' AND ( EventType<>'1' AND EventType<>'2' AND EventType<>'4' )

[Edit] ........Zurückruder.... ------------
Du Wolltest ja auch nur alle gewählten AUSschließen... da passt Deine Bedingung in der Tat.
Nur die Mehrere-EINschließen-Bedingung muss mit "OR"s und/oder Zusatz-Klammern gebastelt werden.

Sorry, hatte schneller getippt als gelesen.
Werde mich bessern...
[/Edit]------------

...Also im Prinzip recht strukturiert.
Hatte vorhin beim Testen auch angefangen, zu basteln, aber.... *axelzuck*
..Bei nur 5 EventTypen, bei denen es ohnehin nur 3 real gibt (ERROR, WARNING, INFO)...
... da werde ich für diese paar Kombinationen keine SQL-String-Generier-Funktionen schreiben.

Da warte ich lieber, bis M$ die ..."where IN LISTE.."/ "where NOT IN LISTE" -Syntax einbaut.

Gruß
Biber
Member: misterdemeanor
misterdemeanor Apr 10, 2006 at 17:33:39 (UTC)
Goto Top
*bg*
NAtürlich hast Du Recht!
So ein Lapsus würde mir auch nicht wirklich passieren, erst ALle Daten zu holen und dann anschließen zu "filtern". War durch meinen/äh seinen Namen total verwirrt *bg*

Ne, generell vollkommen richtig die Where Klausel zu spezifizieren, hast Du Recht *gg

Aber meinste denn das M$ noch was an den WMI´s, etc was ändert, bzw. das was bereits in der Referenz steht aber "Not yet implemented" ist hinzufügt?

Grüße
Felix -misterdemeanor-
Mitglied: 11234
11234 Apr 11, 2006 at 09:01:41 (UTC)
Goto Top
*holla*

Ich bin überrascht über die rege Beteilung und Hilfsbereitschaft. Erstmal vielen vielen Dank dafür!!!

Als VBS-Einsteiger fällt es mir etwas schwierig bei dem ganzen Code-Gewusel noch den wirklichen Durchblick zu behalten, allerdings ist mir der folgende Teil aufgefallen wo ich sagen würde das das die Lösung wäre.

...
where = "Logfile='Application' "

For i = LBound([array()]) To
UBound([array()])
If i <> UBound([array()]) Then
where = where & " AND
EventType<>" & array(i)
End If
Next
...

Doch wie implementiere ich das nun mit in die Anwendung? Ich kann doch nicht gleich im SQL String eine for-Schleife anwenden oder habe ich was verpasst face-smile

LG Felix *gg
Member: misterdemeanor
misterdemeanor Apr 11, 2006 at 12:00:21 (UTC)
Goto Top
In SQL gibt es keine Schleifen, richtig.

In dem Code-Schnipsel der For Schleife wird die WHERE Klausel des SQL-Strings zusammengebastelt.
Nach dieser Schleife hast Du dann (entsprechend der Werte im Array) in der Variablen where zB folgenden Text : "Logfile='Application' AND EventType<>1 AND EventType<>3".

Kompletter Code zur Ausgabe wäre dann also :

On Error Resume Next
  filter() = Array(3,2)
	
  sql = "SELECT * FROM Win32_NTLogEvent WHERE LogFile='Application' "  

  For i = LBound(filter) To UBound(filter)
	sql = sql & " AND EventType<>" & filter(i)  
  Next

  Set objWMIService = GetObject("winmgmts:" & "\\.\root\cimv2")      
  Set colLoggedEvents = objWMIService.ExecQuery(sql)    
  For Each objEvent In colLoggedEvents
    WScript.Echo "Category: " & objEvent.Category  
    WScript.Echo "Computer Name: " & objEvent.ComputerName  
    WScript.Echo "Event Code: " & objEvent.EventCode  
    WScript.Echo "Message: " & objEvent.Message  
    WScript.Echo "Record Number: " & objEvent.RecordNumber  
    WScript.Echo "Source Name: " & objEvent.SourceName  
    WScript.Echo "Time Written: " & objEvent.TimeWritten  
    WScript.Echo "Event Type: " & objEvent.Type  
    WScript.Echo "User: " & objEvent.User  
  Next

Du solltest Dir halt im klaren darüber sein das die "ExecQuery([arg])" einen (SQL) String als Argument erwartet. Die Variable sql im obigen Code ist ja nur eine Variable die mit Text gefüllt wird(welcher ein SQL-Statement darstellt) der dann der ExecQuery-Funktion übergeben wird und von dieser dann ausgeführt wird.
Mitglied: 11234
11234 Apr 11, 2006 at 19:14:38 (UTC)
Goto Top
Super vielen Dank!!! Das war genau das was ich gebraucht habe. Vielleicht komme ich später nochmal drauf zurück wenn ich probleme haben sollten beim Einlesen der XML-Datei. Aber bis zu diesem Punkt vielen dank an alle Beteiligten für die große mühe die ihr euch gemacht habt ;)
Member: misterdemeanor
misterdemeanor Apr 11, 2006 at 21:16:46 (UTC)
Goto Top
Schade!
Als aller-aller-aller-Erstes hätte Dir "filter" auffallen müssen!
Es ist immerhin ein Schlüsselwort in VBS und sollte mit auskommentierung von "On Error Resume Next" sofort zum stoppen des Scriptes führen.

Nun ja, von dieser "Kleinigkeit" abgesehen sind natürlich noch gut ein dutzend Dinge zu beachten welche einen Fehler auslösen würden.

Da Dir in VBS praktisch keine Fehlerbehandlung möglich ist, musst Du auf alle /Eventualitäten/ eingehen.

Ich lege Dir wirklich ans Herz Dich hier einzulesen.

Sollten DANN noch weitere Fragen auftauchen, sind Biber* und ich sicher immer noch da um Dir unter die Arme zu greifen.

Grüße
Felix

*:Biber wurde ohne Ihres/Seines Wissens in obige Behauptung einbezogen.
Member: Biber
Biber Apr 12, 2006 at 06:26:40 (UTC)
Goto Top
@misterdemeanor
*:Biber wurde ohne Ihres/Seines Wissens in obige Behauptung einbezogen.
"seines Wissens" ist schon okay - ich heiße ja BibER und nicht BibSIE..

Und stehe natürlich auch zur Verfügung.
Gruß
der/die/das Biber
Member: misterdemeanor
misterdemeanor Apr 12, 2006 at 09:23:49 (UTC)
Goto Top
hät ich Pfeife natürlich nur /genau/ in Deine Info gucken müssen.

-->männlich

Ich gelobe Besserung *gg*

Grüße
Felix
Member: edgeball
edgeball Apr 15, 2008 at 09:53:03 (UTC)
Goto Top
Hallo

Ich suche genau ein Script für VBA. Doch leider funktioniert dein Beispiel bei mir nicht. Der kommt mit dem objEvent nicht klar... Denke mal ich brauche die richtige Referenz..