Dateiüberwachung -Hinzufügen oder Entfernen- in einem Verzeichnis per VBScript
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.
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.
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.
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:
Eventlog Mailer
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:@echo off
if not exist Switch1.txt (if not exist Switch0.txt (echo 1 >Switch0.txt))
if exist Switch0.txt (set DirFile=Content0.txt) else (set DirFile=Content1.txt)
dir Logs /b /o /a-d err*.log 1>%DirFile% 2>Null
if exist Content0.txt (if exist Content1.txt (fc Content0.txt Content1.txt >Unterschied.log))
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:
Eventlog Mailer
Das Script
' Dateiüberwachung in einem Verzeichnis
' *************************************
' V1.0 02.Nov.2007
' Letzte Änderung: 02.Nov.2007
'
' Autor: Christian Coppes
' kann in SCOM oder anderen Schedulern (z.B. "Geplante Tasks") zur Überwachung von Verzeichnissen eingesetzt werden
'
' Die Datei muß mit irgendeiner Art von Scheduler in regelmäßigen Abständen aufgerufen werden.
' Je nach Größe des Zielverzeichnisses sollte man die Zeit nicht zu kurz wählen, damit das Skript nicht
' läuft, während eine alte Instanz noch nicht fertig ist.
' Es empfiehlt sich, einen Wert von ca. 1 Minute nicht zu unterschreiten.
' Mit den Konstanten unten kann man die Parameter an eigene Bedürfnisse anpassen.
'
' Funktionsweise: Per CMD-"dir"-Befehl wird der Inhalt des gewünschten Verzeichnisses
' unter Verwendung von FILEMASK abwechselnd in die Datei DIRFILE0 und DIRFILE1 eingetragen.
'
' Zur Feststellung, welche Datei zuletzt verwendet wurde, dient die Datei SWITCHFILE0, die dann
' abwechselnd in SWITCHFILE1 umbenannt wird.
'
' Es wird daraufhin festgestellt, welche die neuere DIRFILE ist, um die Änderung gegenüber der älteren
' zu protokollieren.
'
' Die beiden DIRFILEs werden in jeweils ein Array eingelesen, die ältere Datei immer in "Zeile0",
' die neuere immer in "Zeile1".
'
' Mit Hilfe des VBScript-Filter-Befehls wird dann Zeile für Zeile verglichen, welche Zeile in der älteren
' Datei nicht vorhanden ist und diese in das Array "Hinzu1" eingefügt. Umgekehrt wird dann der Vergleich
' durchgeführt, um Zeilen, die in der neueren Datei nicht mehr enthalten sind, in "Weg1" zu schreiben.
'
' Zuletzt wird für beide Gruppen je ein Event im Application Event Log angelegt. Über die Konstanten kann
' man festlegen, ob auch die entfernten Dateien protokolliert werden und welche Art von Event dabei
' generiert werden soll.
'
' Darüber hinaus wird nur ein Event generiert für alle hinzugekommenen und ein Event für alle gelöschten
' Dateien, um die Anzahl der Events nicht zu groß werden zu lassen.
'
' Die Events können dann beispielsweise mit SCOM (Microsoft System Center Operations Manager) ausgewertet werden.
'
' Folgende DOS-Batchdatei prüft ebenfalls auf Dateiunterschiede.
' Dies ist die VBS-Version, die ein wenig komfortabler ist.
'
'@echo off
'if not exist Switch1.txt (if not exist Switch0.txt (echo 1 >Switch0.txt))
'if exist Switch0.txt (set DirFile=Content0.txt) else (set DirFile=Content1.txt)
'dir Logs /b /o /a-d err*.log 1>%DirFile% 2>Null
'if exist Content0.txt (if exist Content1.txt (fc Content0.txt Content1.txt >Unterschied.log))
'if exist Switch1.txt (ren Switch1.txt Switch0.txt) else (ren Switch0.txt Switch1.txt)
'echo On
' Verzeichnis (absolut oder relativ zum Skriptpfad), in dem die Dateien protokolliert werden sollen
Const LOGDIR = "Z:\Public\Compare\Logs"
' Dateien, die gesucht werden sollen
Const FILEMASK = "err*.log"
' Art der verwendeten Logbucheinträge, 0 = Success, 1 = Error, 2 = Warning, 4 = Information
Const NEWEVENT = 1
Const DELEVENT = 2
' Diese temporären Dateien werden für den Vergleich benötigt.
' Das Script muß in diesen Verzeichnissen Schreibrechte haben.
Const DIRFILE0 = "C:\Windows\Debug\Content0.txt"
Const DIRFILE1 = "C:\Windows\Debug\Content1.txt"
Const SWITCHFILE0 = "C:\Windows\Debug\Switch0.txt"
Const SWITCHFILE1 = "C:\Windows\Debug\Switch1.txt"
' NewDel = 1: Alle Unterschiede protokollieren
' NewDel = 0: Nur neu hinzugekommene Dateien protokollieren
Const NewDel = 1
Dim i, j, EventStr, AnzHinzu, AnzWeg
Dim Datei,SwitchFile, DirFile
Dim objFSO, objShell
Dim Zeile0(), Zeile1()
Dim Hinzu, Hinzu1()
Dim Weg, Weg1()
Dim DummyFile
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
'
' Wurde schon eine Switchdatei erstellt?
If ((Not objFSO.FileExists(SWITCHFILE0)) And _
(Not objFSO.FileExists(SWITCHFILE1))) Then
' Switch-Datei erzeugen
Set SwitchFile=objFSO.OpenTextFile(SWITCHFILE0,2,true)
SwitchFile.WriteLine "1" ' Dummyinhalt
SwitchFile.Close
End If
' Schalterdatei prüfen und den Dateinamen für das Inhaltsverzeichnis
' entsprechend einstellen (abwechselndes Schreiben)
If objFSO.FileExists(SWITCHFILE0) Then
DirFile=DIRFILE0
Else
DirFile=DIRFILE1
End If
' Alle Err-Dateien aus dem Ordner sortiert in eine der beiden Content-
' Dateien schreiben
objShell.Run("%windir%\system32\cmd.exe /c dir "+ LOGDIR +" /b /o /a-d " + FILEMASK + " 1>"+DirFile+" 2>Null")
' Am Ende der Ausführung Schalter für den nächsten Durchlauf "umlegen"
If objFSO.FileExists(SWITCHFILE0) Then
'Datei umbenennen
objFSO.MoveFile SWITCHFILE0 , SWITCHFILE1
Else
objFSO.MoveFile SWITCHFILE1 , SWITCHFILE0
End If
' *****************************************************
' Dateivergleich zwischen Content0.txt und Content1.txt
' *****************************************************
' In "Zeile0" immer die ältere Datei einlesen und
' in "Zeile1" immer die neuere
If DirFile = DIRFILE0 Then
DirFileAlt = DIRFILE1
DirFileNeu = DIRFILE0
Else
DirFileAlt = DIRFILE0
DirFileNeu = DIRFILE1
End If
'DIRFILE0 zeilenweise lesen
Set DummyFile=objFSO.OpenTextFile(DirFileAlt,1,true)
i=0
Do until DummyFile.AtEndOfStream
ReDim Preserve Zeile0(i)
Zeile0(i)=DummyFile.ReadLine
i=i+1
Loop
DummyFile.Close
Set DummyFile=Nothing
'DIRFILE1 zeilenweise lesen
Set DummyFile=objFSO.OpenTextFile(DirFileNeu,1,true)
i=0
Do until DummyFile.AtEndOfStream
ReDim Preserve Zeile1(i)
Zeile1(i)=DummyFile.ReadLine
i=i+1
Loop
DummyFile.Close
Set DummyFile=Nothing
' Hinzugekommene Dateien in das Array "Hinzu1" schreiben
AnzHinzu=-1
For i = 0 To UBound(Zeile1)
Hinzu = Filter(Zeile0,Zeile1(i),True)
If UBound(Hinzu)=-1 Then
AnzHinzu = AnzHinzu + 1
ReDim Preserve Hinzu1(AnzHinzu)
Hinzu1(AnzHinzu)=Zeile1(i)
End If
Next
' Entfernte Dateien in das Array "Weg1" schreiben
If NewDel = 1 then
AnzWeg=-1
For i = 0 To UBound(Zeile0)
Weg = Filter(Zeile1,Zeile0(i),True)
If UBound(Weg)=-1 Then
AnzWeg = AnzWeg + 1
ReDim Preserve Weg1(AnzWeg)
Weg1(AnzWeg)=Zeile0(i)
End If
Next
End If
If AnzHinzu > -1 Then
' Event für hinzugekommene Dateien in das Logbuch schreiben
EventStr = "Neu hinzugekommene Dateien vom Typ "+FILEMASK+" :" + vbCrLF
EventStr = EventStr + Join(Hinzu1,vbCrLf)
objShell.LogEvent NEWEVENT, EventStr
'WScript.Echo("EventHinzu: "+EventStr)
End If
If NewDel = 1 Then
If AnzWeg > -1 Then
EventStr = "Entfernte Dateien vom Typ "+FILEMASK+" :" + vbCrLF
EventStr = EventStr + Join(Weg1,vbCrLf)
' Event für entfernte Dateien in das Logbuch schreiben
objShell.LogEvent DELEVENT, EventStr
'WScript.Echo("EventWeg: "+EventStr)
End If
End If
Please also mark the comments that contributed to the solution of the article
Content-ID: 72662
Url: https://administrator.de/contentid/72662
Printed on: December 7, 2024 at 20:12 o'clock
14 Comments
Latest comment
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 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:
' Dateiüberwachung in einem Verzeichnis
' *************************************
' V1.0.1 04.Nov.2007
' Letzte Änderung: 04.Nov.2007
'
' Autor: Christian Coppes
' Kann in SCOM oder anderen Schedulern (z.B. "Geplante Tasks") zur Überwachung von Verzeichnissen eingesetzt werden
'
' Die Datei muss mit irgendeiner Art von Scheduler in regelmäßigen Abständen aufgerufen werden.
' Je nach Größe des Zielverzeichnisses sollte man die Zeit nicht zu kurz wählen, damit das Skript nicht
' läuft, während eine alte Instanz noch nicht fertig ist.
' Es empfiehlt sich, einen Wert von ca. 1 Minute nicht zu unterschreiten.
' Mit den Konstanten unten kann man die Parameter an eigene Bedürfnisse anpassen.
'
' Funktionsweise: Per CMD-"dir"-Befehl wird der Inhalt des gewünschten Verzeichnisses unter
' Verwendung von FILEMASK eingelesen und in DIRFILE für den nächsten Vergleich zwischengespeichert.
'
' Die beiden Dateilisten werden in jeweils ein Array eingelesen, die ältere Liste immer in "Zeile0",
' die neuere immer in "Zeile1".
'
' Mit Hilfe des VBScript-Filter-Befehls wird dann Zeile für Zeile verglichen, welche Zeile in der älteren
' Datei nicht vorhanden ist und diese in den String "Hinzu1" eingefügt. Umgekehrt wird dann der Vergleich
' durchgeführt, um Zeilen, die in der neueren Datei nicht mehr enthalten sind, in "Weg1" zu schreiben.
'
' Zuletzt wird für beide Gruppen je ein Event im Application Event Log angelegt. Über die Konstanten kann
' man festlegen, ob auch die entfernten Dateien protokolliert werden und welche Art von Event dabei
' generiert werden soll.
'
' Darüber hinaus wird nur ein Event generiert für alle hinzugekommenen und ein Event für alle gelöschten
' Dateien, um die Anzahl der Events nicht zu groß werden zu lassen.
'
' Die Events können dann beispielsweise mit SCOM (Microsoft System Center Operations Manager) ausgewertet werden.
'
' Folgende DOS-Batchdatei prüft ebenfalls auf Dateiunterschiede.
'
'@echo off
'set "Logs=Z:\Public\Compare\Logs"
'set "FileMask=err*.log"
'set "DFPath=C:\Windows\Debug"
'if not exist "%DFPath\Switch1.txt" (if not exist "%DFPath%\Switch0.txt" (echo 1 >"%DFPath%\Switch0.txt"))
'if exist "%DFPath%\Switch0.txt" (set "DirFile=%DFPath%\Content0.txt") else (set "DirFile=%DFPath%\Content1.txt")
'dir "%Logs%\%FileMask%" /b /o /a-d>"%DirFile%" 2>Null
'if exist "%DFPath%\Content0.txt" (if exist "%DFPath%\Content1.txt" (fc "%DFPath%\Content0.txt" "%DFPath%\Content1.txt" >"%DFPath%\Unterschied.log"))
'if exist "%DFPath%\Switch1.txt" (move "%DFPath%\Switch1.txt" "%DFPath%\Switch0.txt") else (move "%DFPath%\Switch0.txt" "%DFPath%\Switch1.txt" 2>nul)
' Dies ist die VBS-Version, die ein wenig komfortabler ist:
' Verzeichnis, in dem die Dateien protokolliert werden sollen
Const LOGDIR = "Z:\Public\Compare\Logs"
' Dateien, die gesucht werden sollen
Const FILEMASK = "err*.log"
' Art der verwendeten Logbucheinträge, 0 = Success, 1 = Error, 2 = Warning, 4 = Information
Const NEWEVENT = 1
Const DELEVENT = 2
' Diese temporäre Datei wird für den Vergleich benötigt. Das Script muss im verwendeten Verzeichnis Schreibrechte haben.
Const DIRFILE = "C:\Windows\Debug\Content.txt"
' NewDel = 1: Alle Unterschiede protokollieren
' NewDel = 0: Nur neu hinzugekommene Dateien protokollieren
Const 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 = "%windir%\system32\cmd.exe /c dir " & LOGDIR & " /b /o /a-d " & FILEMASK & " 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
End If 'Es sind Dateien hinzugekommen
If NewDel = 1 Then 'Auch gelöschte Dateien protokollieren
' Entfernte Dateien in "Weg1" schreiben
Weg1 = ""
For i = 0 To UBound(Zeile0)
Weg = Filter(Zeile1, Zeile0(i), True)
If UBound(Weg) = -1 Then Weg1 = Weg1 & vbCrLF & Zeile0(i)
Next
If Weg1 <> "" Then 'Es wurden Dateien entfernt
' Event für entfernte Dateien in das Logbuch schreiben
EventStr = "Entfernte Dateien vom Typ " & FILEMASK & " :"
EventStr = EventStr & Weg1
' objShell.LogEvent DELEVENT, EventStr
WScript.Echo("EventWeg: " & EventStr & vbCrLF) 'zu Demozwecken Ausgabe anstatt Event-Eintrag
End If 'Es wurden Dateien entfernt
End If 'Auch gelöschte Dateien protokollieren
Else
WScript.Echo "Keine Unterschiede gefunden!" 'Ausgabe zu Demozwecken
End If 'Dateiliste hat sich verändert
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
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:
strCMD = objShell.ExpandEnvironmentStrings("%WinDir%") & "\system32\cmd.exe /c dir " & LOGDIR & "\" & FILEMASK & " /b /od /a-d 2>nul"
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
Grüße
bastla
Je nach Typ kann man auch den Temp- (1) oder System32-Folder (2) bekommen.
Dann wäre eigentlich in diesem Fall der Ordner "System32" vorzuziehen - der Wert dafür ist allerdings 1; mit 2 erhältst Du den "Temp"-Ordner ...Grüße
bastla
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.
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:WScript.Echo Mid(Replace(Hinzu1, vbCrLF, ";"), 2)
for /f "delims=" %%i in ('cscript //nologo C:\Scripts\DeinScriptName.vbs') do set "Neue=%%i"
objFSO.OpenTextFile("D:\NeueDateien.txt", 2, True).Write Mid(Replace(Hinzu1, vbCrLF, ";"), 2)
Grüße
bastla
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