Monitorowanie zdarzeń systemowych. (vbs)   strona główna:
A po co ten Excel ;-)
 
 
     Kiedyś trafiłem na dwa artykuły:  
Monitoring Events using WMI  
Unlocking the Mystery of WMI Events in MOM  
 
Testuję od jakiegoś czasu możliwości tych Eventów i choć nie wykorzystuję tych procedur do jakiegokolwiek konkretnego celu to   
myślę że warto przedstawić choćby moje dotychczasowe testy. Możliwości związane z tymi procedurami uważam za obiecujące.  
A wykorzystanie… zobaczy się … ;-)   Listy class których zdarzenia
  można monitorować
Pierwszą procedurą jaką testowałem była: Win32_Process.vbs   Win32 Classes
  CIM Classes
    sComputer = "."  
    strWQL = "SELECT * " & _  
         "FROM __InstanceCreationEvent " & _   wykorzystywane w przykładach:
         "WITHIN 1 " & _   Win32_Process class
         "WHERE TargetInstance ISA 'Win32_Process'"   CIM_DataFile class
     Win32_Directory class
    Set objWMIService = GetObject("winmgmts:\\" & sComputer & "\root\cimv2")  
    Set colMonitoredEvents = objWMIService.ExecNotificationQuery(strWQL)  
  WQL (SQL for WMI)
    WScript.Echo Now & Chr(10) & _  
            "Rozpocząto monitorowanie zdarzeń: Win32_Process"  
 
    On Error Resume Next  
    Do  
        Set objLatestEvent = colMonitoredEvents.NextEvent  
 
       With objLatestEvent  
           strText = strText & Now & Chr(10)  
           strText = strText & "Path_.Class: " & .Path_.Class & Chr(10) & Chr(10)  
          
       With .TargetInstance  
        strText = strText & "TargetInstance:" & Chr(10)  
        strText = strText & ".Caption: " & .Caption & Chr(10)  
        strText = strText & ".CommandLine: " & .CommandLine & Chr(10)  
        strText = strText & ".Description: " & .Description & Chr(10)  
        strText = strText & ".ExecutablePath: " & .ExecutablePath & Chr(10)  
        strText = strText & ".Name: " & .Name & Chr(10)  
       End With  
    End With  
 
    WScript.Echo strText  
    strText = ""  
 
    k = k + 1  
    If k > 5 Then  
        WScript.Echo "Koniec zabawy :-)"  
            Exit Do  
        End If  
    Loop  
 
    On Error GoTo 0  
 
    Set objWMIService = Nothing  
    Set colMonitoredEvents = Nothing  
    Set objLatestEvent = Nothing  
 
Procedura w WScript.Echo zwraca właściwości ostatniego zaistniałego zdarzenia Win32_Process - wywołanych programów.  
Odpaliłem więc Worda, Excela, Paina. Program zwraca nazwę programu który włączyłem, ścieżkę pliku exe tego programu i w  
zależności od wybranych właściwości inne dane nt wywołanego Procesu. Listę wszystkich właściwości znajdziecie pod linkami  
wyżej - w części: "wykorzystane w przykładach"  
    Działa fajnie ale nie zwraca nazwy pliku który otworzono np. w Excelu. Jak więc sprawdzić jaki plik otwarto??  
testExcel.vbs  
 
    sComputer = "."  
 
    strWQL = "Select * " & _  
         "From __InstanceCreationEvent " & _  
         "Within 1 " & _  
         "Where TargetInstance Isa ""Win32_Process"" " & _  
         "AND TargetInstance.Name = 'excel.exe'"  
    
    Set objWMIService = GetObject("winmgmts:\\" & sComputer & "\root\cimv2")  
    Set colMonitoredEvents = objWMIService.ExecNotificationQuery(strWQL)  
 
    WScript.Echo Now & Chr(10) & _  
            "Rozpocząto monitorowanie: Excel.Exe"  
 
    On Error Resume Next  
 
    Do  
        Set objLatestEvent = colMonitoredEvents.NextEvent  
          
    Select Case objLatestEvent.Path_.Class  
        Case "__InstanceCreationEvent"  
 
        Dim xlApp: Set xlApp = GetObject(, "Excel.Application")  
        WScript.Echo xlApp.ActiveWorkbook.FullName
 
        Set xlApp = Nothing  
 
        Case Else  
        MsgBox "INNE ZDARZENIE: " & objLatestEvent.Path_.Class  
 
    End Select  
 
    k = k + 1  
    If k > 2 Then  
        WScript.Echo "Koniec zabwy :-)"  
            Exit Do  
        End If  
    Loop  
 
    On Error GoTo 0  
 
    Set objWMIService = Nothing  
    Set colMonitoredEvents = Nothing  
    Set objLatestEvent = Nothing  
 
… ale jeśli otworzymy sam program a następnie z Menu Otwórz jakiś plik to zdarzenie nie nastąpi :-) Nie jest to więc dobry   Application Events
sposób na monitorowanie zdarzeń Excela - do takich celów służy przechwytywanie zdarzeń Aplikacji. Ale jako zabawka - fajne :-)  
 
    Inną ciekawostką jest wykorzystanie zdarzeń classy CIM_DataFile a więc przechwytywanie zdarzeń plików.  
CIM_DataFile.vbs  
 
    Dim sComputer: sComputer = "."  
    Dim sDrive: sDrive = "D:"  
      
    Dim arrPaths(1), iArr  
    arrPaths(0) = "\\tkuchta1\\"  
    arrPaths(1) = "\\tkuchta1\\UE1\\"  
      
    Dim strOR, strSQL  
    strOR = "(TargetInstance.Path='" & arrPaths(0)  
    For iArr = 1 To UBound(arrPaths)  
        strOR = strOR & "' OR "  
        strOR = strOR & "TargetInstance.Path='" & arrPaths(iArr)  
    Next  
    strOR = strOR & "')"  
 
    strSQL = "SELECT * " & _  
         "FROM __InstanceOperationEvent WITHIN 1 " & _  
         "WHERE TargetInstance ISA 'CIM_DataFile' AND " & _  
               "TargetInstance.Drive='" & sDrive & "' AND " & strOR  
 
    'Debug.Print strOR & vbCrLf & strSQL  
 
    Set objWMIService = GetObject("winmgmts:\\" & sComputer & "\root\cimv2")  
    Set colMonitoredEvents = objWMIService.ExecNotificationQuery(strSQL)  
 
    WScript.Echo Now & Chr(10) & _  
                 "Rozpocząto monitorowanie folderów: " & vbCrLf & _  
                 Join(arrPaths, vbCrLf)  
 
    On Error Resume Next  
 
    '-----------------------zdarzenia plików-------------------------  
    Do  
        Set objLatestEvent = colMonitoredEvents.NextEvent  
 
        With objLatestEvent  
            strText = Now & vbTab & .Path_.Class & Chr(10)  
            strText = strText & "Filename: " & .TargetInstance.Filename & Chr(10)  
            strText = strText & "Extension: " & .TargetInstance.Extension & Chr(10)  
            strText = strText & "LastModified: " & .TargetInstance.LastModified & Chr(10)  
            strText = strText & "Pr.LastModified: " & .PreviousInstance.LastModified & Chr(10)  
        strText = strText & (.TargetInstance.LastModified <> .PreviousInstance.LastModified)  
                    
        End With  
 
        WScript.Echo strText  
        strText = vbNullString  
 
        k = k + 1  
        If k > 5 Then  
            WScript.Echo "Koniec zabawy :-)"  
            Exit Do  
        End If  
    Loop  
    '----------------------------------------------------------------  
 
 
    Set objWMIService = Nothing  
    Set colMonitoredEvents = Nothing  
    Set objLatestEvent = Nothing  
 
Procedura ta ma za zadanie monitorować zdarzenia plików w określonych lokalizacjach.  
 
    Dim sDrive: sDrive = "D:"  
      
    Dim arrPaths(1), iArr  
    arrPaths(0) = "\\tkuchta1\\"  
    arrPaths(1) = "\\tkuchta1\\UE1\\"  
  fajny przykład!!
Tak określam foldery w których pliki będą monitorowane. Nie są monitorowane pod foldery. Nie działa tu operator LIKE :-(   WMI and File System Monitoring
Ale można nawypisywać "od groma" ścieżek w tablicy arrPaths. Ja wsadziłem 82 elementy a Len(strSQL) zwracało 5412 znaków!! i,  
choć wolno się ładowało, to program działał!! :-) Szybciej bym napisał funkcje która zwróci taką tablicę z pod folderów -co wam  
raczej polecam zamiast wypisywać kolejne ścieżki!! :-)  
    Można monitorować zdarzenia:   
          utworzenia pliku "__InstanceCreationEvent"  
          usunięcia "__InstanceDeletionEvent"  
          lub modyfikacji "__InstanceModificationEvent"  
 
Inna częścią zdarzeń są zdarzenia Folderów np: utworzenie/usunięcie Folderu, zmiana zawartości folderu.  
O ile zmiana zawartości folderu łączy się ze zdarzeniami plików to pozostałe można monitorować przez Win32_Directory.vbs  
 
    Dim sComputer: sComputer = "."  
 
    strSQL = "SELECT * " & _  
             "FROM __InstanceOperationEvent WITHIN 1 " & _  
             "WHERE TargetInstance ISA 'Win32_Directory'" & _  
             "AND TargetInstance.Drive = 'D:'"  
 
    Set objWMIService = GetObject("winmgmts:\\" & sComputer & "\root\cimv2")  
    Set colMonitoredEvents = objWMIService.ExecNotificationQuery(strSQL)  
 
    WScript.Echo Now & Chr(10) & _  
                 "Rozpocząto monitorowanie folderów z d:"  
 
    On Error Resume Next  
 
    '-----------------------zdarzenia folderów-------------------------  
    Do  
        Set objLatestEvent = colMonitoredEvents.NextEvent  
 
    With objLatestEvent  
        strText = .Path_.Class & Chr(10) & Chr(10)  
        With .TargetInstance  
            strText = strText & "Filename: " & .Filename & Chr(10)  
            strText = strText & "Extension:" & .Extension & Chr(10)  
            strText = strText & "CreationClassName:" & .CreationClassName & Chr(10)  
            strText = strText & "Description:" & .Description & Chr(10)  
            strText = strText & "FileType:" & .FileType & Chr(10)  
            strText = strText & "LastModified:" & .LastModified & Chr(10)  
            strText = strText & "Name:" & .Name & Chr(10)  
            strText = strText & "Path:" & .Path & Chr(10)  
        End With  
    End With  
      
    WScript.Echo strText  
    strText = vbNullString  
      
        k = k + 1  
        If k > 5 Then  
            WScript.Echo "Koniec zabawy :-)"  
            Exit Do  
        End If  
    Loop  
    '----------------------------------------------------------------  
 
 
    Set objWMIService = Nothing  
    Set colMonitoredEvents = Nothing  
    Set objLatestEvent = Nothing  
 
W tej procedurze nie ma koniczności określania wszystkich ścieżek do pod folderów które są monitorowane. Myślę że chodzi o   
zależność pomiędzy zawartości pod folderu a folderu głównego. Jeżeli coś zmieni się w pod folderze to jakby zawartość folderu też  
się zmieniła. Procedura zwraca jednak ścieżki do zmienianego FOLDERU a nie pliku który wpłynął na zmianę…  
 
Można próbować łączyć obie grupy zdarzeń np.: CIM_DataFile i Win32_Directory.vbs  
 
    Dim sComputer: sComputer = "."  
    Dim sDrive: sDrive = "D:"  
      
    Dim arrPaths(1), iArr  
    arrPaths(0) = "\\tkuchta1\\KZP\\"  
    arrPaths(1) = "\\tkuchta1\\UE1\\"  
      
    Dim strOR, strSQL  
    strOR = "(TargetInstance.Path='" & arrPaths(0)  
    For iArr = 1 To UBound(arrPaths)  
        strOR = strOR & "' OR "  
        strOR = strOR & "TargetInstance.Path='" & arrPaths(iArr)  
    Next  
    strOR = strOR & "')"  
 
    strSQL = "SELECT * " & _  
         "FROM __InstanceOperationEvent WITHIN 1 " & _  
         "WHERE (TargetInstance ISA 'CIM_DataFile' OR TargetInstance ISA 'Win32_Directory') AND " & _  
               "TargetInstance.Drive='" & sDrive & "' AND " & strOR  
 
    Set objWMIService = GetObject("winmgmts:\\" & sComputer & "\root\cimv2")  
    Set colMonitoredEvents = objWMIService.ExecNotificationQuery(strSQL)  
 
    Dim k  
 
    WScript.Echo Now & Chr(10) & _  
                 "Rozpocząto monitorowanie folderów: " & vbCrLf & Join(arrPaths, vbCrLf)  
 
    'On Error Resume Next  
 
    '-----------------------zdarzenia-------------------------  
    Do  
        Set objLatestEvent = colMonitoredEvents.NextEvent  
 
        With objLatestEvent  
            strText = Now & vbTab & .Path_.Class & Chr(10) & Chr(10)  
      
            With .TargetInstance  
                strText = strText & .Path_.Class & Chr(10) & Chr(10)  
          
                Select Case .Path_.Class  
                Case "Win32_Directory"  
                       strText = strText & "Description: " & .Description & Chr(10)  
                       strText = strText & "FileType: " & .FileType & Chr(10)  
                       strText = strText & "Name: " & .Name & Chr(10)  
                       strText = strText & "Path: " & .Path & Chr(10)  
          
                Case "CIM_DataFile"  
                       strText = strText & "Filename: " & .Filename & Chr(10)  
                       strText = strText & "Extension: " & .Extension & Chr(10)  
                       strText = strText & "FileType: " & .FileType & Chr(10)  
                       strText = strText & "Path: " & .Path & Chr(10)  
          
                Case Else:  
                  
            End Select  
 
        End With  
          
        If Err.Number <> 0 Then strTest = Err.Number & " " & Err.Description  
      
        'strText = strText & "LastModified: "   & .TargetInstance.LastModified      & chr(10)  
        'strText = strText & "Pr.LastModified: "    & .PreviousInstance.LastModified    & chr(10)  
        'strText = strText & "Zmodyfikowano: " &    (.TargetInstance.LastModified <> .PreviousInstance.LastModified)  
                    
    End With  
 
    WScript.Echo strText  
    strText = vbNullString  
 
        k = k + 1  
        If k > 10 Then  
            WScript.Echo "Koniec zabawy :-)"  
            Exit Do  
        End If  
    Loop  
    '----------------------------------------------------------------  
 
 
    Set objWMIService = Nothing  
    Set colMonitoredEvents = Nothing  
    Set objLatestEvent = Nothing  
 
To połącznie obu metod monitorowania zdarzeń. Połącznie to określa się w zapytanie WQL w klauzuli WHERE:  
(TargetInstance ISA 'CIM_DataFile' OR TargetInstance ISA 'Win32_Directory')  
Oczywiście nagle procedura nie będzie działać na zdarzenia plików w pod folderach - niestety. Ale zdarzenia folderów tak.  
  Przykłady w vbs:
Na razie tyle zabawy w temacie :-)   vbs.zip
Grzebie Wam ktoś w kompie pod Waszą nieobecność?? Skrypt bazujący na powyższej technologii do autostartu. "Powiedzieć" temu  
skryptowi kiedy nie powinno być Was za biurkiem, wyposażyć w wysyłanie maila na Waszą komórkę i wyjdzie... :-)  
 
Inne zastosowanie: powiedzmy że w określonej lokalizacji pojawia się co jakiś czas plik z danymi.  Dane te trzeba zaimportować do  
bazy a sam plik usunąć. Jak monitorowanie lokalizacji "uzbroimy" w ADO to całość może wykonywać automat :-)  
Ten pomysł chyba sprawdzę w praktyce… i nie omieszkam Wam pokazać jak to działa!! :-)