Centrum skryptów - Systemy operacyjne

Jak monitorować komunikaty w dzienniku zdarzeń pod kątem określonych słów?

Udostępnij na: Facebook

Skrypciarze odpowiadają na Wasze pytania

Cześć Skrypciarze!

Witamy w rubryce TechNet, w której Skrypciarze z firmy Microsoft odpowiadają na częste pytania dotyczące używania skryptów w administracji systemu. Jeśli macie jakieś pytania z tej dziedziny, zachęcamy do wysłania e-maila na adres: scripter@microsoft.com. Nie możemy zagwarantować odpowiedzi na każde otrzymane pytanie, ale staramy się jak możemy.

Jak monitorować komunikaty w dzienniku zdarzeń pod kątem określonych słów?

Cześć Skrypciarze! Pytanie

Cześć, Skrypciarze! Jak monitorować komunikaty w dzienniku zdarzeń pod względem określonych słów lub zwrotów?

-- GH

Cześć Skrypciarze! Odpowiedź

Cześć, GH. Każdy ma czasem ochotę zrobić coś szalonego w swoim życiu, niektórym nawet się to udaje i przez kilka chwil mogą się poczuć wyjątkowo. Jednak zawsze przychodzi taki moment, kiedy trzeba powrócić do rzeczywistości, co niekiedy bywa bardzo trudne i bolesne. Przydarzyło się to także Skrypciarzowi piszącemu te słowa, jednak udało mu się już przystosować do rzeczywistości. Na dowód przedstawiamy napisany przez niego skrypt, który monitoruje komunikaty w dzienniku zdarzeń pod kątem określonych słów.

I tak na przykład, załóżmy, że mamy skrypt o nazwie Test.vbs. Chcielibyśmy otrzymywać powiadomienia za każdym razem, kiedy zdarzenie wpisane do dziennika zdarzeń zawierać będzie tekst Test.vbs. A jak tego dokonać? Oto sposób:

strComputer = "."



Set objWMIService = GetObject("winmgmts:{(Security)}\\" & _

        strComputer & "\root\cimv2")



Set colEvents = objWMIService.ExecNotificationQuery _    

    ("Select * From __InstanceCreationEvent Where " _

        & "TargetInstance isa 'Win32_NTLogEvent'")



Do

    Set objEvent = colEvents.NextEvent

    If InStr(LCase(objEvent.TargetInstance.Message), "test.vbs") Then

        Wscript.Echo Now

        Wscript.Echo "Category: " & objEvent.TargetInstance.Category

        Wscript.Echo "Event Code: " & objEvent.TargetInstance.EventCode

        Wscript.Echo "Message: " & objEvent.TargetInstance.Message

        Wscript.Echo "Record Number: " & objEvent.TargetInstance.RecordNumber

        Wscript.Echo "Source Name: " & objEvent.TargetInstance.SourceName

        Wscript.Echo "Event Type: " & objEvent.TargetInstance.Type

        Wscript.Echo

    End If

Loop

Jak widać, zaczynamy od połączenia się z usługą WMI na lokalnym komputerze (skrypt ten może także monitorować dzienniki zdarzeń zdalnych komputerów). Zauważmy jednak, że nasz ciąg odpowiedzialny za połączenie zawiera przywilej Security: Set objWMIService = GetObject("winmgmts:{(Security)}\\". Czy to ważne? O tak, pod warunkiem, że chcemy monitorować wszystkie dzienniki zdarzeń, włącznie z dziennikiem zdarzeń Security. Jeżeli tak właśnie jest, należy uwzględnić także przywilej Security. Jeżeli nie jesteśmy zainteresowani dziennikiem zdarzeń Security, odpowiedź brzmi: nie, nie jest to dla nas ważne.

Po podłączeniu do usługi WMI, wysyłamy zapytanie, dzięki któremu będziemy dostawać zawiadomienie za każdym razem, gdy do któregokolwiek dziennika zdarzeń zostanie dopisane nowe zdarzenie:

Set colEvents = objWMIService.ExecNotificationQuery _    

    ("Select * From __InstanceCreationEvent Where " _

        & "TargetInstance ISA 'Win32_NTLogEvent'")

Chodzi nam tutaj o monitorowanie wystąpień nowych obiektów(__InstanceCreationEvent), jednak tylko w wypadku, gdy obiekty te należą do klasy Win32_NTLogEvent. Zauważmy, że w tym zapytaniu nie uwzględniamy „czasów między odpytaniami” (np. WITHIN 10). Dlaczego nie? Ponieważ czasy między odpytaniami są stosowane tylko podczas monitorowania tych klas WMI, które nie mają stałych providerów zdarzeń. W wypadku dzienników zdarzeń jest inaczej. Dzienniki zdarzeń mają stałego dostawcę zdarzeń. Z tego powodu możemy otrzymywać natychmiastowe powiadomienie o nowych zdarzeniach bez konieczności uwzględniania kodu, który zleci usłudze WMI okresowe sprawdzanie, czy nie zostały dopisane nowe zdarzenia.

Uwaga. Jeżeli ktoś czuje niedosyt i ma ochotę przyswoić sobie trochę więcej informacji na temat skryptów monitorujących usługi WMI, jak również terminów typu czasy między odpytaniami, może obejrzeć webcast An Ounce of Prevention: An Introduction to WMI Events (j. ang.).

Po zgłoszeniu zapytania uruchamiamy pętlę Do, która będzie działać bez końca. Jest to powód, dla którego należy uruchomić ten skrypt w oddzielnym oknie poleceń (command window) jako host skryptu CScript; jeżeli kiedykolwiek będziemy chcieli zatrzymać działanie skryptu, można to zrobić zamykając okno, w którym on działa.

Wewnątrz pętli stosujemy poniższy fragment kodu, aby skrypt przeszedł w tryb czekania na zapisanie zdarzenia w jednym z dzienników zdarzeń:

Set objEvent = colEvents.NextEvent

A co się dzieje, kiedy jakiś zdarzenie zostanie zapisane w jednym z dzienników zdarzeń? No cóż, kiedy tak się stanie, stosujemy poniższy wiersz kodu, aby przekonać się, czy komunikat zdarzeń zawiera zwrot test.vbs:

If InStr(LCase(objEvent.TargetInstance.Message), "test.vbs") Then

Co my tu robimy? Otóż najpierw pobieramy właściwość Message z obiektu TargetInstance, który reprezentuje zapis dodany przed chwilą do dziennika zdarzeń. Używamy funkcji LCase w celu przekonwertowania wszystkich znaków znajdujących się w komunikacie na małe litery, a następnie używamy funkcji InStr, aby określić, czy wartość test.vbs znajduje się gdzieś w tym komunikacie. Jeżeli test.vbs nie pojawia się nigdzie w komunikacie, po prostu pozwalamy pętli działać dalej i czekamy na zapis następnego zdarzenia.

Przypuśćmy jednak, że komunikat zdarzenia zawiera tekst test.vbs. W takim wypadku po prostu używamy poniższego bloku kodu, aby wywołać echo informacji o tym zdarzeniu:

Wscript.Echo Now

Wscript.Echo "Category: " & objEvent.TargetInstance.Category

Wscript.Echo "Event Code: " & objEvent.TargetInstance.EventCode

Wscript.Echo "Message: " & objEvent.TargetInstance.Message

Wscript.Echo "Record Number: " & objEvent.TargetInstance.RecordNumber

Wscript.Echo "Source Name: " & objEvent.TargetInstance.SourceName

Wscript.Echo "Event Type: " & objEvent.TargetInstance.Type

Chyba nie ma potrzeby stwierdzać, że jest to całkiem standardowy skrypt usługi WMI – po prostu wywołujemy echo informacji o bieżącej dacie i godzinie (za pomocą funkcji Now), a następnie wywołujemy echo wartości właściwości takich jak: Category, EventCode oraz Message. Jeżeli nie mamy pewności odnośnie tego, do czego służą te wartości właściwości, a ponadto chcielibyśmy uzyskać więcej informacji o dziennikach zdarzeń i klasie Win32_NTLogEvent, możemy zajrzeć do tej części przewodnika Microsoft Windows 2000 Scripting Guide (j.ang.).

Jeżeli natomiast chcielibyśmy przetestować ten skrypt, poniżej znajduje się kod, za pomocą którego można wpisać zdarzenie całkiem przypadkowo zawierające tekst test.vbs do dziennika zdarzeń Application:

Const EVENT_SUCCESS = 0



Set objShell = Wscript.CreateObject("Wscript.Shell")

objShell.LogEvent EVENT_SUCCESS, "Test.vbs started."
 Do początku strony Do początku strony

Centrum skryptów - Systemy operacyjne