bitsqueezer
Goto Top

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.

back-to-topZweck

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.

back-to-topErster 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.

back-to-topLö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

back-to-topDas 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

Content-ID: 72662

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

Printed on: December 7, 2024 at 20:12 o'clock

bastla
bastla Nov 04, 2007 at 14:14:40 (UTC)
Goto Top
Hallo Bitqueezer!

Vorweg ein Dankeschön face-smile 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 face-wink) 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
Bitsqueezer
Bitsqueezer Nov 04, 2007 at 15:07:58 (UTC)
Goto Top
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
Bitsqueezer
Bitsqueezer Nov 04, 2007 at 22:51:27 (UTC)
Goto Top
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
bastla
bastla Nov 05, 2007 at 06:09:30 (UTC)
Goto Top
Hallo Bitsqueezer!

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"  
oder etwas eleganter:
strCMD = objShell.ExpandEnvironmentStrings("%ComSpec%") & " /c dir " & LOGDIR & "\" & FILEMASK & " /b /od /a-d 2>nul"  
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]
goodbytes
goodbytes Jan 30, 2008 at 13:35:15 (UTC)
Goto Top
Hallo,
ein prima Script, echt! face-smile
Ich benutze es zur Ordnerüberwachung ob eine Datei hinzugefügt wurde.
Habe die Schleife für gelöschte Dateien rausgemacht.

Torsten
Bitsqueezer
Bitsqueezer Jan 30, 2008 at 17:48:33 (UTC)
Goto Top
Hallo,

es gibt übrigens noch eine elegante Variante, an das richtige Verzeichnis zu kommen - ganz ohne DOS-Variablen:

Const WINFOLDER = 0
Set objFSO   = CreateObject("Scripting.FileSystemObject")  
strWinDir = objFSO.GetSpecialFolder(WINFOLDER).Path

Je nach Typ kann man auch den Temp- (1) oder System32-Folder (2) bekommen.

Gruß

Christian
bastla
bastla Jan 30, 2008 at 17:56:51 (UTC)
Goto Top
@Bitsqueezer

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
goodbytes
goodbytes Jan 31, 2008 at 18:29:49 (UTC)
Goto Top
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.
bastla
bastla Jan 31, 2008 at 18:44:27 (UTC)
Goto Top
Hallo TorstenB!

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)  
In eine Batch-Variable bekommst Du sie dann so:
for /f "delims=" %%i in ('cscript //nologo C:\Scripts\DeinScriptName.vbs') do set "Neue=%%i"  
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:
objFSO.OpenTextFile("D:\NeueDateien.txt", 2, True).Write Mid(Replace(Hinzu1, vbCrLF, ";"), 2)  
Den Namen des Textfiles solltest Du natürlich besser als Konstante festlegen (vgl etwa "DIRFILE").

Grüße
bastla
goodbytes
goodbytes Jan 31, 2008 at 19:00:37 (UTC)
Goto Top
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
aschinnerl
aschinnerl Mar 21, 2008 at 15:53:33 (UTC)
Goto Top
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
bastla Mar 21, 2008 at 16:32:02 (UTC)
Goto Top
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
goodbytes
goodbytes May 09, 2008 at 10:28:24 (UTC)
Goto Top
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
goodbytes
goodbytes May 14, 2008, updated at Oct 18, 2012 at 16:35:42 (UTC)
Goto Top
Die Lösung zu diesem Problem befindet sich hier.
Vielen Dank nochmal an bastla !!!

Torsten