Dateiüberwachung -Hinzufügen oder Entfernen- in einem Verzeichnis per VBScript
04.11.2007
10:20:09 Uhr19149 Aufrufe
14 Antworten
10:20:09 Uhr
14 Antworten
Noch nicht bewertet
Wie man in einem Verzeichnis das Auftreten oder Löschen von Dateien per VBScript überwachen kann mit Eintrag in das Anwender-Eventlog von Windows. Verwendbar für zum Beispiel MOM/SCOM, "Geplante Tasks" oder mit anderen Schedulern.
Zweck
Sinn dieses Scriptes soll es sein, ein Verzeichnis zu überwachen, um festzustellen, ob ein bestimmter Dateityp auftritt und/oder gelöscht wurde. Das kann man zum Beispiel verwenden, um auf die Ausgabe von Error-Logdateien einer Anwendung schnell reagieren zu können oder um auf einem Fileserver zu prüfen, ob etwa eine MP3-Datei von einem User abgelegt wurde.Um ein Verzeichnis zu überwachen, gibt es sicherlich einige Methoden, von der in NTFS eingebetteten "Überwachung"-Einstellung bis hin zu Tools oder ganzen Softwaresuiten.
Problem ist, wenn man auf Windows-Bordmittel angewiesen und kein teures Zusatztool kaufen möchte, dann hilft nur selbst scripten. Nebeneffekt ist, daß man das folgende Script auch in allen Softwareprodukten einsetzen kann, die das Ausführen von VBScript unterstützen oder die wenigstens Eventlogs auslesen können. Alternativ kann man das Schreiben der Eventlogs natürlich auch in eine Bildschirmausgabe oder in eine Dateiausgabe umlenken, um das Ergebnis auszulesen.
Erster Versuch
Da es unter der Kommandozeilenebene ein nettes Progrämmchen namens "fc" gibt (FileCompare), mit dem man zwei Dateien auf Unterschiede überprüfen kann, war mein erster Versuch das folgende kleine DOS-Batchprogramm:01.
@echo off 02.
if not exist Switch1.txt (if not exist Switch0.txt (echo 1 >Switch0.txt)) 03.
if exist Switch0.txt (set DirFile=Content0.txt) else (set DirFile=Content1.txt) 04.
dir Logs /b /o /a-d err*.log 1>%DirFile% 2>Null 05.
if exist Content0.txt (if exist Content1.txt (fc Content0.txt Content1.txt >Unterschied.log)) 06.
if exist Switch1.txt (ren Switch1.txt Switch0.txt) else (ren Switch0.txt Switch1.txt)Das funktioniert auch, hat nur den Nachteil, daß die Ausgabe von fc wieder so kompliziert ist, daß man sie für eine programmgesteuerte Abfrage wieder regelrecht dekodieren muß, was aufwändiger wäre als das eigentliche Ziel.
Lösung in VBScript
Daher hier nun eine Lösung, wie man das ganze in VBScript durchführen kann. Der Vorteil von VBScript ist, daß es im Gegensatz zur DOS-Batchdatei einen Haufen mehr Möglichkeiten hat, so etwa das Eintragen von Events in das Anwendungs-Eventlog von Windows.Hier kann man alternativ natürlich auch andere Wege gehen, um die Benachrichtigung für das Überwachungsziel auszulösen, ganz nach eigenem Geschmack. Das Eventlog hat den Vorteil, daß es in Softwaresuiten wie MOM/SCOM oder ähnlichen automatisch überwacht werden kann. SCOM könnte beispielsweise eine automatische Löschung von MP3-Dateien durchführen, wenn es sie auf dem Fileserver im überwachten Verzeichnis findet, außerdem kann SCOM selbst der Scheduler zum Ausführen des Scriptes sein.
Alternativ kann man der Scheduler auch jedes andere dafür geeignete Programm sein, also zum Beispiel auch der zu Windows gehörende Taskplaner. Bei der Erstellung unter "Geplante Tasks" kann man zwar nur tageweise Ausführung eingeben, wenn der Task aber erstellt ist, kann man in seinen Eigenschaften bis herunter zu minütlicher Ausführung gehen.
Man sollte allerdings bei sehr großen Verzeichnissen oder langsamen Rechnern die Ausführung nicht zu klein einstellen und auch an die zusätzliche CPU-Belastung auf etwa einem Fileserver denken, wenn das Script zu oft ausgeführt wird. Je nach Größe des überwachten Ordners könnte es auch dazu führen, daß das Script ausgeführt wird, während eine frühere Instanz des Scriptes noch ausgeführt wird, was dann zu einem Durcheinander und Fehlmeldungen führen könnte.
Es ist daher sinnvoll, sich vorher Gedanken darüber zu machen, wie oft man wirklich eine Überwachung eines Ordners benötigt, wie oft man mit dem Auftreten/Löschen der überwachten Dateitypen rechnet und wie schnell man über diese Information verfügen möchte.
Während der Ausführung des Scriptes wird ein "Dir"-Kommando auf Kommandozeilenebene ausgeführt, was zur Folge hat, das ganz kurz ein CMD-Fenster aufblinkt. Wer das störend findet, kann im Internet nach dem kleinen Ersatz "CMDOW" suchen, der ein CMD ohne Fenster ausführt. Hier ging es mir aber darum, wirklich nur Windows-Bordmittel zu verwenden, da man "im Einsatz" in der Regel keine zusätzlichen Tools zur Verfügung hat oder Freeware nicht eingesetzt werden darf.
Weitere Detailerläuterungen zum Script finden sich im Script in den Kommentaren, ebenso eine Erläuterung über die Parameter, die man per Konstanten zu Beginn des Scriptes anpassen kann.
Viel Spaß mit dem Tool und mit dem Experimentieren mit eigenen Erweiterungen. Wer zusätzliche Ideen hat oder Anmerkungen, wie man etwas noch leichter hinbekommen kann, ist herzlich eingeladen, Kommentare zu schreiben. Nothing is perfect.
Christian
PS.: Mit Hilfe des Tutorials, was ich vorhin hier gefunden habe, könnte man das ganze dahingehend erweitern, daß automatisch eine EMail geschickt wird, wenn das Script einen Eintrag in das Eventlog schreibt:
http://www.administrator.de/Eventlog_Mail ...
Das Script
01.
' Dateiüberwachung in einem Verzeichnis 02.
' ************************************* 03.
' V1.0 02.Nov.2007 04.
' Letzte Änderung: 02.Nov.2007 05.
' 06.
' Autor: Christian Coppes 07.
' kann in SCOM oder anderen Schedulern (z.B. "Geplante Tasks") zur Überwachung von Verzeichnissen eingesetzt werden 08.
' 09.
' Die Datei muß mit irgendeiner Art von Scheduler in regelmäßigen Abständen aufgerufen werden. 10.
' Je nach Größe des Zielverzeichnisses sollte man die Zeit nicht zu kurz wählen, damit das Skript nicht 11.
' läuft, während eine alte Instanz noch nicht fertig ist. 12.
' Es empfiehlt sich, einen Wert von ca. 1 Minute nicht zu unterschreiten. 13.
' Mit den Konstanten unten kann man die Parameter an eigene Bedürfnisse anpassen. 14.
' 15.
' Funktionsweise: Per CMD-"dir"-Befehl wird der Inhalt des gewünschten Verzeichnisses 16.
' unter Verwendung von FILEMASK abwechselnd in die Datei DIRFILE0 und DIRFILE1 eingetragen. 17.
' 18.
' Zur Feststellung, welche Datei zuletzt verwendet wurde, dient die Datei SWITCHFILE0, die dann 19.
' abwechselnd in SWITCHFILE1 umbenannt wird. 20.
' 21.
' Es wird daraufhin festgestellt, welche die neuere DIRFILE ist, um die Änderung gegenüber der älteren 22.
' zu protokollieren. 23.
' 24.
' Die beiden DIRFILEs werden in jeweils ein Array eingelesen, die ältere Datei immer in "Zeile0", 25.
' die neuere immer in "Zeile1". 26.
' 27.
' Mit Hilfe des VBScript-Filter-Befehls wird dann Zeile für Zeile verglichen, welche Zeile in der älteren 28.
' Datei nicht vorhanden ist und diese in das Array "Hinzu1" eingefügt. Umgekehrt wird dann der Vergleich 29.
' durchgeführt, um Zeilen, die in der neueren Datei nicht mehr enthalten sind, in "Weg1" zu schreiben. 30.
' 31.
' Zuletzt wird für beide Gruppen je ein Event im Application Event Log angelegt. Über die Konstanten kann 32.
' man festlegen, ob auch die entfernten Dateien protokolliert werden und welche Art von Event dabei 33.
' generiert werden soll. 34.
' 35.
' Darüber hinaus wird nur ein Event generiert für alle hinzugekommenen und ein Event für alle gelöschten 36.
' Dateien, um die Anzahl der Events nicht zu groß werden zu lassen. 37.
' 38.
' Die Events können dann beispielsweise mit SCOM (Microsoft System Center Operations Manager) ausgewertet werden. 39.
' 40.
' Folgende DOS-Batchdatei prüft ebenfalls auf Dateiunterschiede. 41.
' Dies ist die VBS-Version, die ein wenig komfortabler ist. 42.
' 43.
'@echo off 44.
'if not exist Switch1.txt (if not exist Switch0.txt (echo 1 >Switch0.txt)) 45.
'if exist Switch0.txt (set DirFile=Content0.txt) else (set DirFile=Content1.txt) 46.
'dir Logs /b /o /a-d err*.log 1>%DirFile% 2>Null 47.
'if exist Content0.txt (if exist Content1.txt (fc Content0.txt Content1.txt >Unterschied.log)) 48.
'if exist Switch1.txt (ren Switch1.txt Switch0.txt) else (ren Switch0.txt Switch1.txt) 49.
'echo On 50.
51.
' Verzeichnis (absolut oder relativ zum Skriptpfad), in dem die Dateien protokolliert werden sollen 52.
Const LOGDIR = "Z:\Public\Compare\Logs" 53.
' Dateien, die gesucht werden sollen 54.
Const FILEMASK = "err*.log" 55.
' Art der verwendeten Logbucheinträge, 0 = Success, 1 = Error, 2 = Warning, 4 = Information 56.
Const NEWEVENT = 1 57.
Const DELEVENT = 2 58.
59.
' Diese temporären Dateien werden für den Vergleich benötigt. 60.
' Das Script muß in diesen Verzeichnissen Schreibrechte haben. 61.
Const DIRFILE0 = "C:\Windows\Debug\Content0.txt" 62.
Const DIRFILE1 = "C:\Windows\Debug\Content1.txt" 63.
Const SWITCHFILE0 = "C:\Windows\Debug\Switch0.txt" 64.
Const SWITCHFILE1 = "C:\Windows\Debug\Switch1.txt" 65.
66.
' NewDel = 1: Alle Unterschiede protokollieren 67.
' NewDel = 0: Nur neu hinzugekommene Dateien protokollieren 68.
Const NewDel = 1 69.
70.
Dim i, j, EventStr, AnzHinzu, AnzWeg 71.
Dim Datei,SwitchFile, DirFile 72.
Dim objFSO, objShell 73.
74.
Dim Zeile0(), Zeile1() 75.
Dim Hinzu, Hinzu1() 76.
Dim Weg, Weg1() 77.
Dim DummyFile 78.
79.
Set objFSO = CreateObject("Scripting.FileSystemObject") 80.
Set objShell = CreateObject("WScript.Shell") 81.
' 82.
' Wurde schon eine Switchdatei erstellt? 83.
If ((Not objFSO.FileExists(SWITCHFILE0)) And _ 84.
(Not objFSO.FileExists(SWITCHFILE1))) Then 85.
' Switch-Datei erzeugen 86.
Set SwitchFile=objFSO.OpenTextFile(SWITCHFILE0,2,true) 87.
SwitchFile.WriteLine "1" ' Dummyinhalt 88.
SwitchFile.Close 89.
End If 90.
91.
' Schalterdatei prüfen und den Dateinamen für das Inhaltsverzeichnis 92.
' entsprechend einstellen (abwechselndes Schreiben) 93.
If objFSO.FileExists(SWITCHFILE0) Then 94.
DirFile=DIRFILE0 95.
Else 96.
DirFile=DIRFILE1 97.
End If 98.
99.
' Alle Err-Dateien aus dem Ordner sortiert in eine der beiden Content- 100.
' Dateien schreiben 101.
objShell.Run("%windir%\system32\cmd.exe /c dir "+ LOGDIR +" /b /o /a-d " + FILEMASK + " 1>"+DirFile+" 2>Null") 102.
103.
' Am Ende der Ausführung Schalter für den nächsten Durchlauf "umlegen" 104.
If objFSO.FileExists(SWITCHFILE0) Then 105.
'Datei umbenennen 106.
objFSO.MoveFile SWITCHFILE0 , SWITCHFILE1 107.
Else 108.
objFSO.MoveFile SWITCHFILE1 , SWITCHFILE0 109.
End If 110.
111.
' ***************************************************** 112.
' Dateivergleich zwischen Content0.txt und Content1.txt 113.
' ***************************************************** 114.
115.
' In "Zeile0" immer die ältere Datei einlesen und 116.
' in "Zeile1" immer die neuere 117.
If DirFile = DIRFILE0 Then 118.
DirFileAlt = DIRFILE1 119.
DirFileNeu = DIRFILE0 120.
Else 121.
DirFileAlt = DIRFILE0 122.
DirFileNeu = DIRFILE1 123.
End If 124.
125.
'DIRFILE0 zeilenweise lesen 126.
Set DummyFile=objFSO.OpenTextFile(DirFileAlt,1,true) 127.
i=0 128.
Do until DummyFile.AtEndOfStream 129.
ReDim Preserve Zeile0(i) 130.
Zeile0(i)=DummyFile.ReadLine 131.
i=i+1 132.
Loop 133.
DummyFile.Close 134.
Set DummyFile=Nothing 135.
136.
'DIRFILE1 zeilenweise lesen 137.
Set DummyFile=objFSO.OpenTextFile(DirFileNeu,1,true) 138.
i=0 139.
Do until DummyFile.AtEndOfStream 140.
ReDim Preserve Zeile1(i) 141.
Zeile1(i)=DummyFile.ReadLine 142.
i=i+1 143.
Loop 144.
DummyFile.Close 145.
Set DummyFile=Nothing 146.
147.
' Hinzugekommene Dateien in das Array "Hinzu1" schreiben 148.
AnzHinzu=-1 149.
For i = 0 To UBound(Zeile1) 150.
Hinzu = Filter(Zeile0,Zeile1(i),True) 151.
If UBound(Hinzu)=-1 Then 152.
AnzHinzu = AnzHinzu + 1 153.
ReDim Preserve Hinzu1(AnzHinzu) 154.
Hinzu1(AnzHinzu)=Zeile1(i) 155.
End If 156.
Next 157.
158.
' Entfernte Dateien in das Array "Weg1" schreiben 159.
If NewDel = 1 then 160.
AnzWeg=-1 161.
For i = 0 To UBound(Zeile0) 162.
Weg = Filter(Zeile1,Zeile0(i),True) 163.
If UBound(Weg)=-1 Then 164.
AnzWeg = AnzWeg + 1 165.
ReDim Preserve Weg1(AnzWeg) 166.
Weg1(AnzWeg)=Zeile0(i) 167.
End If 168.
Next 169.
End If 170.
171.
If AnzHinzu > -1 Then 172.
' Event für hinzugekommene Dateien in das Logbuch schreiben 173.
EventStr = "Neu hinzugekommene Dateien vom Typ "+FILEMASK+" :" + vbCrLF 174.
EventStr = EventStr + Join(Hinzu1,vbCrLf) 175.
objShell.LogEvent NEWEVENT, EventStr 176.
'WScript.Echo("EventHinzu: "+EventStr) 177.
End If 178.
179.
180.
If NewDel = 1 Then 181.
If AnzWeg > -1 Then 182.
EventStr = "Entfernte Dateien vom Typ "+FILEMASK+" :" + vbCrLF 183.
EventStr = EventStr + Join(Weg1,vbCrLf) 184.
' Event für entfernte Dateien in das Logbuch schreiben 185.
objShell.LogEvent DELEVENT, EventStr 186.
'WScript.Echo("EventWeg: "+EventStr) 187.
End If 188.
End If
bastla schreibt am 04.11.2007 um 15:14:40 Uhr
Hallo Bitqueezer!
Vorweg ein Dankeschön
für Deine Mühe und das daraus entstandene Ergebnis - Verwendung für Dein Script gibt es sicherlich.
Anhand einer auf Deinem Code aufbauenden Version 1.0.1 (und aufgrund Deiner Einladung dazu
) möchte ich einige Anmerkungen anbringen:
Eigentlich genügt es, die jeweils letzte Dateiliste zwischenzuspeichern - damit entfällt auch die Verwendung des Schalters (der Schalter-Datei). Realisieren lässt sich dies, indem das Ergebnis des aktuellen "Dir"-Befehles unter Verwendung von "Shell.Exec" und "StdOut" gleich in eine Variable eingelesen, per "Split" auf Zeilen aufgeteilt und nach dem Einlesen der alten Liste am Stück in die Datei geschrieben wird.
Erforderlich ist es IMHO, sich gegen das Einlesen einer leeren Dateiliste abzusichern. Auch in dieser Version noch nicht enthalten ist eine Überprüfung des Zielverzeichnisses auf Schreibrechte.
Da ich gerne "ReDim Preserve" vermeide, verwende ich zum Einlesen von Textdateien die dargestellte "ReadAll"-"Split"-Variante - ob es in diesem Fall tatsächlich Performance-Vorteile bringt, lasse ich einmal dahingestellt.
Analog dazu können die Ausgabezeilen in Strings gesammelt werden (da sie ja später ohnehin ge"join"ed werden sollen). Dadurch wird auch noch ein Zähler / Schalter eingespart.
Gleichfalls einsparen lässt sich - durch den Vorab-Vergleich der (in je einem String konzentrierten) alten und neuen Dateiliste - für den Fall, dass sich der Verzeichnisinhalt nicht geändert hat, der Durchlauf der Dateilisten-Arrays. Die Ausgabe eines Hinweises bei unveränderter Dateiliste habe ich nur zu Demozwecken eingebaut.
Schließlich kann Erstellung und Ausgabe des Protokolls für gelöschte Dateien auch in einem einzigen "If" abgewickelt werden.
Grüße
bastla
Vorweg ein Dankeschön
Anhand einer auf Deinem Code aufbauenden Version 1.0.1 (und aufgrund Deiner Einladung dazu
01.
' Dateiüberwachung in einem Verzeichnis 02.
' ************************************* 03.
' V1.0.1 04.Nov.2007 04.
' Letzte Änderung: 04.Nov.2007 05.
' 06.
' Autor: Christian Coppes 07.
' Kann in SCOM oder anderen Schedulern (z.B. "Geplante Tasks") zur Überwachung von Verzeichnissen eingesetzt werden 08.
' 09.
' Die Datei muss mit irgendeiner Art von Scheduler in regelmäßigen Abständen aufgerufen werden. 10.
' Je nach Größe des Zielverzeichnisses sollte man die Zeit nicht zu kurz wählen, damit das Skript nicht 11.
' läuft, während eine alte Instanz noch nicht fertig ist. 12.
' Es empfiehlt sich, einen Wert von ca. 1 Minute nicht zu unterschreiten. 13.
' Mit den Konstanten unten kann man die Parameter an eigene Bedürfnisse anpassen. 14.
' 15.
' Funktionsweise: Per CMD-"dir"-Befehl wird der Inhalt des gewünschten Verzeichnisses unter 16.
' Verwendung von FILEMASK eingelesen und in DIRFILE für den nächsten Vergleich zwischengespeichert. 17.
' 18.
' Die beiden Dateilisten werden in jeweils ein Array eingelesen, die ältere Liste immer in "Zeile0", 19.
' die neuere immer in "Zeile1". 20.
' 21.
' Mit Hilfe des VBScript-Filter-Befehls wird dann Zeile für Zeile verglichen, welche Zeile in der älteren 22.
' Datei nicht vorhanden ist und diese in den String "Hinzu1" eingefügt. Umgekehrt wird dann der Vergleich 23.
' durchgeführt, um Zeilen, die in der neueren Datei nicht mehr enthalten sind, in "Weg1" zu schreiben. 24.
' 25.
' Zuletzt wird für beide Gruppen je ein Event im Application Event Log angelegt. Über die Konstanten kann 26.
' man festlegen, ob auch die entfernten Dateien protokolliert werden und welche Art von Event dabei 27.
' generiert werden soll. 28.
' 29.
' Darüber hinaus wird nur ein Event generiert für alle hinzugekommenen und ein Event für alle gelöschten 30.
' Dateien, um die Anzahl der Events nicht zu groß werden zu lassen. 31.
' 32.
' Die Events können dann beispielsweise mit SCOM (Microsoft System Center Operations Manager) ausgewertet werden. 33.
' 34.
' Folgende DOS-Batchdatei prüft ebenfalls auf Dateiunterschiede. 35.
' 36.
'@echo off 37.
'set "Logs=Z:\Public\Compare\Logs" 38.
'set "FileMask=err*.log" 39.
'set "DFPath=C:\Windows\Debug" 40.
'if not exist "%DFPath\Switch1.txt" (if not exist "%DFPath%\Switch0.txt" (echo 1 >"%DFPath%\Switch0.txt")) 41.
'if exist "%DFPath%\Switch0.txt" (set "DirFile=%DFPath%\Content0.txt") else (set "DirFile=%DFPath%\Content1.txt") 42.
'dir "%Logs%\%FileMask%" /b /o /a-d>"%DirFile%" 2>Null 43.
'if exist "%DFPath%\Content0.txt" (if exist "%DFPath%\Content1.txt" (fc "%DFPath%\Content0.txt" "%DFPath%\Content1.txt" >"%DFPath%\Unterschied.log")) 44.
'if exist "%DFPath%\Switch1.txt" (move "%DFPath%\Switch1.txt" "%DFPath%\Switch0.txt") else (move "%DFPath%\Switch0.txt" "%DFPath%\Switch1.txt" 2>nul) 45.
46.
' Dies ist die VBS-Version, die ein wenig komfortabler ist: 47.
48.
' Verzeichnis, in dem die Dateien protokolliert werden sollen 49.
Const LOGDIR = "Z:\Public\Compare\Logs" 50.
' Dateien, die gesucht werden sollen 51.
Const FILEMASK = "err*.log" 52.
53.
' Art der verwendeten Logbucheinträge, 0 = Success, 1 = Error, 2 = Warning, 4 = Information 54.
Const NEWEVENT = 1 55.
Const DELEVENT = 2 56.
57.
' Diese temporäre Datei wird für den Vergleich benötigt. Das Script muss im verwendeten Verzeichnis Schreibrechte haben. 58.
Const DIRFILE = "C:\Windows\Debug\Content.txt" 59.
60.
' NewDel = 1: Alle Unterschiede protokollieren 61.
' NewDel = 0: Nur neu hinzugekommene Dateien protokollieren 62.
Const NewDel = 1 63.
64.
Set objFSO = CreateObject("Scripting.FileSystemObject") 65.
Set objShell = CreateObject("WScript.Shell") 66.
67.
'Alte Liste aus DIRFILE in Array Zeile0() einlesen 68.
If objFSO.FileExists(DIRFILE) Then 'DIRFILE vorhanden 69.
Set objDirFile = objFSO.OpenTextFile(DIRFILE, 1) 70.
If Not objDirFile.AtEndOfStream Then 'DIRFILE nicht leer 71.
strZeile0 = objDirFile.ReadAll 72.
Zeile0 = Split(strZeile0, vbCrLF) 73.
Else 74.
Zeile0 = Array("") 75.
End If 'DIRFILE nicht leer 76.
Else 77.
Zeile0 = Array("") 78.
End If 'DIRFILE vorhanden 79.
80.
' Alle Err-Dateien aus dem Ordner sortiert in das Array Zeile1() einlesen 81.
strCMD = "%windir%\system32\cmd.exe /c dir " & LOGDIR & " /b /o /a-d " & FILEMASK & " 2>nul" 82.
strZeile1 = objShell.Exec(strCMD).StdOut.ReadAll 83.
Zeile1 = Split(strZeile1, vbCrLF) 84.
85.
' Am Ende der Ausführung aktuelle Dateiliste in DIRFILE speichern 86.
objFSO.OpenTextFile(DIRFILE, 2, True).Write strZeile1 87.
88.
' ************************************************************************* 89.
' Dateivergleich zwischen Content.txt (Zeile0) und aktueller Liste (Zeile1) 90.
' ************************************************************************* 91.
92.
If LCase(Trim(strZeile0)) <> LCase(Trim(strZeile1)) Then 'Dateiliste hat sich verändert 93.
94.
' Hinzugekommene Dateien in "Hinzu1" schreiben 95.
Hinzu1 = "" 96.
For i = 0 To UBound(Zeile1) 97.
Hinzu = Filter(Zeile0, Zeile1(i), True) 98.
If UBound(Hinzu) = -1 Then Hinzu1 = Hinzu1 & vbCrLF & Zeile1(i) 99.
Next 100.
101.
If Hinzu1 <> "" Then 'Es sind Dateien hinzugekommen 102.
' Event für hinzugekommene Dateien in das Logbuch schreiben 103.
EventStr = "Neu hinzugekommene Dateien vom Typ " & FILEMASK & " :" 104.
EventStr = EventStr & Hinzu1 105.
' objShell.LogEvent NEWEVENT, EventStr 106.
WScript.Echo("EventHinzu: " & EventStr & vbCrLF) 'zu Demozwecken Ausgabe anstatt Event-Eintrag 107.
End If 'Es sind Dateien hinzugekommen 108.
109.
If NewDel = 1 Then 'Auch gelöschte Dateien protokollieren 110.
' Entfernte Dateien in "Weg1" schreiben 111.
Weg1 = "" 112.
For i = 0 To UBound(Zeile0) 113.
Weg = Filter(Zeile1, Zeile0(i), True) 114.
If UBound(Weg) = -1 Then Weg1 = Weg1 & vbCrLF & Zeile0(i) 115.
Next 116.
117.
If Weg1 <> "" Then 'Es wurden Dateien entfernt 118.
' Event für entfernte Dateien in das Logbuch schreiben 119.
EventStr = "Entfernte Dateien vom Typ " & FILEMASK & " :" 120.
EventStr = EventStr & Weg1 121.
' objShell.LogEvent DELEVENT, EventStr 122.
WScript.Echo("EventWeg: " & EventStr & vbCrLF) 'zu Demozwecken Ausgabe anstatt Event-Eintrag 123.
End If 'Es wurden Dateien entfernt 124.
End If 'Auch gelöschte Dateien protokollieren 125.
126.
Else 127.
WScript.Echo "Keine Unterschiede gefunden!" 'Ausgabe zu Demozwecken 128.
End If 'Dateiliste hat sich verändertEigentlich genügt es, die jeweils letzte Dateiliste zwischenzuspeichern - damit entfällt auch die Verwendung des Schalters (der Schalter-Datei). Realisieren lässt sich dies, indem das Ergebnis des aktuellen "Dir"-Befehles unter Verwendung von "Shell.Exec" und "StdOut" gleich in eine Variable eingelesen, per "Split" auf Zeilen aufgeteilt und nach dem Einlesen der alten Liste am Stück in die Datei geschrieben wird.
Erforderlich ist es IMHO, sich gegen das Einlesen einer leeren Dateiliste abzusichern. Auch in dieser Version noch nicht enthalten ist eine Überprüfung des Zielverzeichnisses auf Schreibrechte.
Da ich gerne "ReDim Preserve" vermeide, verwende ich zum Einlesen von Textdateien die dargestellte "ReadAll"-"Split"-Variante - ob es in diesem Fall tatsächlich Performance-Vorteile bringt, lasse ich einmal dahingestellt.
Analog dazu können die Ausgabezeilen in Strings gesammelt werden (da sie ja später ohnehin ge"join"ed werden sollen). Dadurch wird auch noch ein Zähler / Schalter eingespart.
Gleichfalls einsparen lässt sich - durch den Vorab-Vergleich der (in je einem String konzentrierten) alten und neuen Dateiliste - für den Fall, dass sich der Verzeichnisinhalt nicht geändert hat, der Durchlauf der Dateilisten-Arrays. Die Ausgabe eines Hinweises bei unveränderter Dateiliste habe ich nur zu Demozwecken eingebaut.
Schließlich kann Erstellung und Ausgabe des Protokolls für gelöschte Dateien auch in einem einzigen "If" abgewickelt werden.
Grüße
bastla
Bitsqueezer schreibt am 04.11.2007 um 16:07:58 Uhr
Hallo Bastla,
vielen Dank für Deine schnelle Anpassung des Scripts - ist in der Tat noch sehr viel besser als meine Version. Je weniger Dateien gelesen/geschrieben werden müssen, desto besser.
Ich bin in VBScript noch nicht so weit, daher kannte ich einige Deiner Techniken noch nicht. Beispielsweise wußte ich noch nicht, daß man die DOS-Ausgaben auch wieder zurück an VBScript umleiten kann. Gute Idee!
Habe Deine Scriptverbesserung bei mir getestet, geht ohne Probleme.
Gruß
Christian
vielen Dank für Deine schnelle Anpassung des Scripts - ist in der Tat noch sehr viel besser als meine Version. Je weniger Dateien gelesen/geschrieben werden müssen, desto besser.
Ich bin in VBScript noch nicht so weit, daher kannte ich einige Deiner Techniken noch nicht. Beispielsweise wußte ich noch nicht, daß man die DOS-Ausgaben auch wieder zurück an VBScript umleiten kann. Gute Idee!
Habe Deine Scriptverbesserung bei mir getestet, geht ohne Probleme.
Gruß
Christian
Bitsqueezer schreibt am 04.11.2007 um 23:51:27 Uhr
Hallo Bastla,
habe heute dann auch mal versucht, das Script als Rule in SCOM einzubauen. Leider gab es dabei Probleme.
1. Offenbar schnallt ein Script unter SCOM keine CMD-Variablen, daher muß man das %windir% gegen einen festen Pfad "C:\Windows" ersetzen, dann wird zumindest der DIR-Befehl richtig ausgeführt.
2. Nach diversen Tests mit meinem alten und Deinem Script zeigte sich, daß mein altes Script die entsprechenden Events erzeugt, während Dein Script zwar die Content.txt erzeugt, der Inhalt aber immer leer ist. Ich vermute, das SCOM ein Problem damit hat, die Ausgabe des CMD wieder an das Script zurückzuleiten.
3. Auch mein altes Skript hat irgendwo noch eine Macke. Wärhend es beim Direktaufruf funktioniert, hat es sich jetzt entschieden, sich in seiner Funktion umzukehren. Wenn ich eine Datei hinzufüge, wird sie als entfernt bezeichnet und umgekehrt. Irgendwo ist da noch ein kleiner Bug...
Gruß
Christian
habe heute dann auch mal versucht, das Script als Rule in SCOM einzubauen. Leider gab es dabei Probleme.
1. Offenbar schnallt ein Script unter SCOM keine CMD-Variablen, daher muß man das %windir% gegen einen festen Pfad "C:\Windows" ersetzen, dann wird zumindest der DIR-Befehl richtig ausgeführt.
2. Nach diversen Tests mit meinem alten und Deinem Script zeigte sich, daß mein altes Script die entsprechenden Events erzeugt, während Dein Script zwar die Content.txt erzeugt, der Inhalt aber immer leer ist. Ich vermute, das SCOM ein Problem damit hat, die Ausgabe des CMD wieder an das Script zurückzuleiten.
3. Auch mein altes Skript hat irgendwo noch eine Macke. Wärhend es beim Direktaufruf funktioniert, hat es sich jetzt entschieden, sich in seiner Funktion umzukehren. Wenn ich eine Datei hinzufüge, wird sie als entfernt bezeichnet und umgekehrt. Irgendwo ist da noch ein kleiner Bug...
Gruß
Christian
bastla schreibt am 05.11.2007 um 07:09:30 Uhr
Hallo Bitsqueezer!
Kurzer Hinweis zu 1.: Du könntest es so versuchen:
oder etwas eleganter:
wobei aber eigentlich die "cmd.exe" über %PATH% gefunden werden müsste und die Angabe des "System32"-Pfades kaum nötig sein sollte (aber sicher ist sicher).
2. und 3. kann ich mir erst später ansehen ...
Grüße
bastla
[Edit] Ergänzung der Variante mit %ComSpec% und Anpassung des "dir"-Befehles [/Edit]
Kurzer Hinweis zu 1.: Du könntest es so versuchen:
01.
strCMD = objShell.ExpandEnvironmentStrings("%WinDir%") & "\system32\cmd.exe /c dir " & LOGDIR & "\" & FILEMASK & " /b /od /a-d 2>nul"01.
strCMD = objShell.ExpandEnvironmentStrings("%ComSpec%") & " /c dir " & LOGDIR & "\" & FILEMASK & " /b /od /a-d 2>nul"2. und 3. kann ich mir erst später ansehen ...
Grüße
bastla
[Edit] Ergänzung der Variante mit %ComSpec% und Anpassung des "dir"-Befehles [/Edit]
Bitsqueezer schreibt am 30.01.2008 um 18:48:33 Uhr
Hallo,
es gibt übrigens noch eine elegante Variante, an das richtige Verzeichnis zu kommen - ganz ohne DOS-Variablen:
Je nach Typ kann man auch den Temp- (1) oder System32-Folder (2) bekommen.
Gruß
Christian
es gibt übrigens noch eine elegante Variante, an das richtige Verzeichnis zu kommen - ganz ohne DOS-Variablen:
01.
Const WINFOLDER = 0 02.
Set objFSO = CreateObject("Scripting.FileSystemObject") 03.
strWinDir = objFSO.GetSpecialFolder(WINFOLDER).PathJe nach Typ kann man auch den Temp- (1) oder System32-Folder (2) bekommen.
Gruß
Christian
TorstenB schreibt am 31.01.2008 um 19:29:49 Uhr
Ich löse dann bei einer Änderung mittels Batch paar verschiedene Ereignisse aus (ein kurzes "net send" und eine Mail per SMTP mit Hilfe des kleinen Tools "sendmail.exe").
Darüber halt:
Set WSHShell = WScript.CreateObject("WScript.Shell") 'Batch-Datei an Eingabeaufforderung übergeben
WSHShell.Run("cmd.exe /c meinebatch.cmd"), 0, True
Kann ich denn die neu hinzugekommenen Dateien in dem überwachten Ordner in eine Variable speichern und irgendwie der aufgerufenen Batch übergeben?
Ich möchte diese Variable bei "net send" und im Body bei "sendmail.exe" weiterbenutzen.
Darüber halt:
Set WSHShell = WScript.CreateObject("WScript.Shell") 'Batch-Datei an Eingabeaufforderung übergeben
WSHShell.Run("cmd.exe /c meinebatch.cmd"), 0, True
Kann ich denn die neu hinzugekommenen Dateien in dem überwachten Ordner in eine Variable speichern und irgendwie der aufgerufenen Batch übergeben?
Ich möchte diese Variable bei "net send" und im Body bei "sendmail.exe" weiterbenutzen.
bastla schreibt am 31.01.2008 um 19:44:27 Uhr
Hallo TorstenB!
In eine Batch-Variable bekommst Du sie dann so:
Soferne es sich um eine kleinere Anzahl von Dateien handelt, sollte es so klappen (wobei zu beachten ist, dass es dann keine weiteren "WScript.Echo"-Befehle geben darf), ansonsten würde es sich anbieten, sie in eine Textdatei zu schreiben:
Den Namen des Textfiles solltest Du natürlich besser als Konstante festlegen (vgl etwa "DIRFILE").
Grüße
bastla
Kann ich denn die neu hinzugekommenen Dateien in dem überwachten Ordner in eine Variable speichern und irgendwie der aufgerufenen Batch übergeben?
Die hinzugekommenen Dateien werden in der VBS-Variablen "Hinzu1" gespeichert, allerdings mit Zeilenschaltungen, was für die Übergabe in eine Batch-Variable hinderlich ist. Mit der folgenden Zeile kannst Du sie aber trotzdem ausgeben:01.
WScript.Echo Mid(Replace(Hinzu1, vbCrLF, ";"), 2)01.
for /f "delims=" %%i in ('cscript //nologo C:\Scripts\DeinScriptName.vbs') do set "Neue=%%i"01.
objFSO.OpenTextFile("D:\NeueDateien.txt", 2, True).Write Mid(Replace(Hinzu1, vbCrLF, ";"), 2)Grüße
bastla
TorstenB schreibt am 31.01.2008 um 20:00:37 Uhr
Hallo bastla,
vielen Dank, ich werds morgen früh gleich mal probieren.
Normalerweise kann es auch nicht so viel werden; das Script läuft alle 15min und in der Zeit dürften wenns hoch kommt drei Dateien reinkommen.
Einen schönen Abend noch !!!
Torsten
vielen Dank, ich werds morgen früh gleich mal probieren.
Normalerweise kann es auch nicht so viel werden; das Script läuft alle 15min und in der Zeit dürften wenns hoch kommt drei Dateien reinkommen.
Einen schönen Abend noch !!!
Torsten
aschinnerl schreibt am 21.03.2008 um 16:53:33 Uhr
Ich habe das Problem das immer in einem Verzeichnis Ordner gelöscht werden. Kann ich mit dem Script den Hauptordner überwachen so das ich verstellen kann wer den Ordner gelöscht hat?
bastla schreibt am 21.03.2008 um 17:32:02 Uhr
Hallo aschinnerl!
Soferne ich Dein Vorhaben richtig interpretiere, wäre es sinnvoll, einen neuen Thread zu starten - hier geht es nur darum, generell festzustellen, dass sich der Inhalt eines Ordners geändert hat, und nicht um die Frage, wer die Änderung verursacht hat.
Grüße
bastla
Soferne ich Dein Vorhaben richtig interpretiere, wäre es sinnvoll, einen neuen Thread zu starten - hier geht es nur darum, generell festzustellen, dass sich der Inhalt eines Ordners geändert hat, und nicht um die Frage, wer die Änderung verursacht hat.
Grüße
bastla
TorstenB schreibt am 09.05.2008 um 12:28:24 Uhr
Hallo,
wie könnte ich es denn anstellen, das das Script nicht überprüft, ob neue Dateien hinzugekommen sind, sondern ob beim Lauf noch Dateien darin liegen, welche beim letzten Lauf schon drin waren. Wenn mindestens eine gefunden wird soll die Batch ausgeführt werden.
Hintergrund: Ein POP3-Connector holt die Mails vom Provider ab und übergibt sie dem Exchange-Server. Beim Abholen landen die Mails temporär in einem Ordner, bevor sie nacheinander an den Exchange übergeben werden. Wenn bei dieser Übergabe was schiefgeht bleiben diese Dateien hier liegen. In diesem Fall soll die Batch ausgelöst werden. Es muss also genau die Dateinamen in der Liste mit denen in dem TEMP-Ordner überprüft werden.
Hier mein momentanes Script:
' Ordnerüberwachung:
' Art der verwendeten Logbucheinträge, 0 = Success, 1 = Error, 2 = Warning, 4 = Information
NEWEVENT = 1
DELEVENT = 2
' Verzeichnis, in dem die Dateien protokolliert werden sollen
LOGDIR = "C:\TMP\"
' Dateien, die gesucht werden sollen
FILEMASK = "*.msg"
' Art der verwendeten Logbucheinträge, 0 = Success, 1 = Error, 2 = Warning, 4 = Information
NEWEVENT = 1
DELEVENT = 2
' Diese temporäre Datei wird für den Vergleich benötigt. Das Script muss im verwendeten Verzeichnis Schreibrechte haben.
DIRFILE = "C:\Programme\POPcon\Log.txt"
' NewDel = 1: Alle Unterschiede protokollieren
' NewDel = 0: Nur neu hinzugekommene Dateien protokollieren
NewDel = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
'Alte Liste aus DIRFILE in Array Zeile0() einlesen
If objFSO.FileExists(DIRFILE) Then 'DIRFILE vorhanden
Set objDirFile = objFSO.OpenTextFile(DIRFILE, 1)
If Not objDirFile.AtEndOfStream Then 'DIRFILE nicht leer
strZeile0 = objDirFile.ReadAll
Zeile0 = Split(strZeile0, vbCrLF)
Else
Zeile0 = Array("")
End If 'DIRFILE nicht leer
Else
Zeile0 = Array("")
End If 'DIRFILE vorhanden
' Alle Err-Dateien aus dem Ordner sortiert in das Array Zeile1() einlesen
strCMD = objShell.ExpandEnvironmentStrings("%ComSpec%") & " /c dir " & LOGDIR & "\" & FILEMASK & " /b /od /a-d 2>nul"
strZeile1 = objShell.Exec(strCMD).StdOut.ReadAll
Zeile1 = Split(strZeile1, vbCrLF)
' Am Ende der Ausführung aktuelle Dateiliste in DIRFILE speichern
objFSO.OpenTextFile(DIRFILE, 2, True).Write strZeile1
' *
' Dateivergleich zwischen Content.txt (Zeile0) und aktueller Liste (Zeile1)
' *
If LCase(Trim(strZeile0)) <> LCase(Trim(strZeile1)) Then 'Dateiliste hat sich verändert
' Hinzugekommene Dateien in "Hinzu1" schreiben
Hinzu1 = ""
For i = 0 To UBound(Zeile1)
Hinzu = Filter(Zeile0, Zeile1(i), True)
If UBound(Hinzu) = -1 Then Hinzu1 = Hinzu1 & vbCrLF & Zeile1(i)
Next
If Hinzu1 <> "" Then 'Es sind Dateien hinzugekommen
' Event für hinzugekommene Dateien in das Logbuch schreiben
EventStr = "Neu hinzugekommene Dateien vom Typ " & FILEMASK & " :"
EventStr = EventStr & Hinzu1
' objShell.LogEvent NEWEVENT, EventStr
'WScript.Echo("EventHinzu: " & EventStr & vbCrLF) 'zu Demozwecken Ausgabe anstatt Event-Eintrag
Set WSHShell = WScript.CreateObject("WScript.Shell") 'Batch-Datei an Eingabeaufforderung übergeben
WSHShell.Run("cmd.exe /c MeineBatch.cmd"), 0, True
End If 'Es sind Dateien hinzugekommen
Else
'WScript.Echo "Keine Unterschiede gefunden!" 'Ausgabe zu Demozwecken
End If 'Dateiliste hat sich verändert
Torsten
wie könnte ich es denn anstellen, das das Script nicht überprüft, ob neue Dateien hinzugekommen sind, sondern ob beim Lauf noch Dateien darin liegen, welche beim letzten Lauf schon drin waren. Wenn mindestens eine gefunden wird soll die Batch ausgeführt werden.
Hintergrund: Ein POP3-Connector holt die Mails vom Provider ab und übergibt sie dem Exchange-Server. Beim Abholen landen die Mails temporär in einem Ordner, bevor sie nacheinander an den Exchange übergeben werden. Wenn bei dieser Übergabe was schiefgeht bleiben diese Dateien hier liegen. In diesem Fall soll die Batch ausgelöst werden. Es muss also genau die Dateinamen in der Liste mit denen in dem TEMP-Ordner überprüft werden.
Hier mein momentanes Script:
' Ordnerüberwachung:
' Art der verwendeten Logbucheinträge, 0 = Success, 1 = Error, 2 = Warning, 4 = Information
NEWEVENT = 1
DELEVENT = 2
' Verzeichnis, in dem die Dateien protokolliert werden sollen
LOGDIR = "C:\TMP\"
' Dateien, die gesucht werden sollen
FILEMASK = "*.msg"
' Art der verwendeten Logbucheinträge, 0 = Success, 1 = Error, 2 = Warning, 4 = Information
NEWEVENT = 1
DELEVENT = 2
' Diese temporäre Datei wird für den Vergleich benötigt. Das Script muss im verwendeten Verzeichnis Schreibrechte haben.
DIRFILE = "C:\Programme\POPcon\Log.txt"
' NewDel = 1: Alle Unterschiede protokollieren
' NewDel = 0: Nur neu hinzugekommene Dateien protokollieren
NewDel = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
'Alte Liste aus DIRFILE in Array Zeile0() einlesen
If objFSO.FileExists(DIRFILE) Then 'DIRFILE vorhanden
Set objDirFile = objFSO.OpenTextFile(DIRFILE, 1)
If Not objDirFile.AtEndOfStream Then 'DIRFILE nicht leer
strZeile0 = objDirFile.ReadAll
Zeile0 = Split(strZeile0, vbCrLF)
Else
Zeile0 = Array("")
End If 'DIRFILE nicht leer
Else
Zeile0 = Array("")
End If 'DIRFILE vorhanden
' Alle Err-Dateien aus dem Ordner sortiert in das Array Zeile1() einlesen
strCMD = objShell.ExpandEnvironmentStrings("%ComSpec%") & " /c dir " & LOGDIR & "\" & FILEMASK & " /b /od /a-d 2>nul"
strZeile1 = objShell.Exec(strCMD).StdOut.ReadAll
Zeile1 = Split(strZeile1, vbCrLF)
' Am Ende der Ausführung aktuelle Dateiliste in DIRFILE speichern
objFSO.OpenTextFile(DIRFILE, 2, True).Write strZeile1
' *
' Dateivergleich zwischen Content.txt (Zeile0) und aktueller Liste (Zeile1)
' *
If LCase(Trim(strZeile0)) <> LCase(Trim(strZeile1)) Then 'Dateiliste hat sich verändert
' Hinzugekommene Dateien in "Hinzu1" schreiben
Hinzu1 = ""
For i = 0 To UBound(Zeile1)
Hinzu = Filter(Zeile0, Zeile1(i), True)
If UBound(Hinzu) = -1 Then Hinzu1 = Hinzu1 & vbCrLF & Zeile1(i)
Next
If Hinzu1 <> "" Then 'Es sind Dateien hinzugekommen
' Event für hinzugekommene Dateien in das Logbuch schreiben
EventStr = "Neu hinzugekommene Dateien vom Typ " & FILEMASK & " :"
EventStr = EventStr & Hinzu1
' objShell.LogEvent NEWEVENT, EventStr
'WScript.Echo("EventHinzu: " & EventStr & vbCrLF) 'zu Demozwecken Ausgabe anstatt Event-Eintrag
Set WSHShell = WScript.CreateObject("WScript.Shell") 'Batch-Datei an Eingabeaufforderung übergeben
WSHShell.Run("cmd.exe /c MeineBatch.cmd"), 0, True
End If 'Es sind Dateien hinzugekommen
Else
'WScript.Echo "Keine Unterschiede gefunden!" 'Ausgabe zu Demozwecken
End If 'Dateiliste hat sich verändert
Torsten










