Batch in Echtzeit auf eine Datei warten


7

Ich habe einige Batch-Skripte, die auf Dateien warten. Die Warteschleife wird mit der typischen IF EXISTS-Schleife ausgeführt:

:waitloop
IF EXISTS file.zip GOTO waitloopend
sleep.exe 60
goto waitloop
: waitloopend

Ich suche nach einer effizienteren Möglichkeit, auf Dateien zu warten. So etwas wie ein Befehl waitfile.exe, der blockiert und wartet, bis die Datei angezeigt wird. Intern sollte die FileSystemWatcher- Klasse verwendet werden, um das Programm beenden zu können, sobald die Datei angezeigt wird.

Unter Linux habe ich mein eigenes Perl-Skript, das intern Inotify verwendet.

Wissen Sie, ob es ein solches Tool gibt?


Sie können die Wartezeit für eine schnellere Reaktion wahrscheinlich sicher auf 1 Sekunde reduzieren. Das Überprüfen der Dateirexistenz ist keine große Belastung für das System, wenn Sie dies einmal pro Sekunde statt einmal pro Minute tun.
Joey

Die Dateien befinden sich auf einem Remote-Dateiserver (Samba). Vor einiger Zeit musste ich die Schlafzeit wegen Überlastung des Dateiservers von 5 auf 60 Sekunden erhöhen. Ich habe Dutzende von Prozessen, die darauf warten, dass Dateien auf dem Dateiserver angezeigt werden. Wahrscheinlich sollte ich eine Art IPC verwenden, anstatt abzufragen ...
Francisco R

Ah, ok, SMB ist ein Argument, besonders die alte Version. SMB 2 hat viel getan, um Latenzprobleme zu reduzieren, aber afaik Sambe ist noch nicht da, obwohl es mittlerweile 4 Jahre alt ist
Joey

Hilft dies: superuser.com/questions/226828/… ? - Dort gibt es eine .vbs-Datei, die Ihr Problem lösen könnte.
Remco

Antworten:


2

Ihre Methode ist vorzuziehen und durchaus akzeptabel. FileSystemWatcherverschwendet Ressourcen, sogar mehr als Ihre Schleife.

Selbst wenn Sie Ihre Schleife so eng wie mit einer Verzögerung von einer Sekunde machen, werden Sie in jedem Prozessmonitor, der die CPU- oder Festplattenlast misst, völlig unbemerkt bleiben.

Übrigens können Sie den timeoutBefehl anstelle von verwenden sleep.exe.

Außerdem haben Sie einige Tippfehler in Ihrem Code:

:waitloop
IF EXIST "scanning.done" GOTO waitloopend
timeout /t 1
goto waitloop
:waitloopend

Einige Informationen zum Thema "Verschwendung von Ressourcen" finden Sie hier: /programming/239988/filesystemwatcher-vs-polling-to-watch-for-file-changes ; Der Hauptpunkt ist, dass es unzuverlässig sein könnte. Aber ich muss zugeben, meine Antwort stammt hauptsächlich aus jahrelanger Praxis und Erfahrung.


Können Sie eine glaubwürdige Quelle für die Anweisung "FileSystemWatcher verschwendet Ressourcen" angeben?
Thomas Weller

Sie schreiben "FileSystemWatcher verschwendet Ressourcen, sogar mehr als Ihre Schleife." Ihr eigener Link enthält jedoch die Antwort "Ich würde das Abrufen der Datei als redundant betrachten und den Aufwand nicht wert sein, es sei denn, Sie misstrauen dem FileSystemWatcher von Natur aus". Nirgendwo in diesem SO-Thread behauptet jemand, dass FileSystemWatcher mehr Ressourcen verschwendet als das Abrufen. Es stellt sich auch die Frage, wie oft die Umfrage durchgeführt wird.
Barlop

0

Ein typischer Dateisystemmonitor erkennt Dateierstellungen und wenn die Datei erstellt wird, während das Tool aktiv ist, erhalten Sie das Ereignis. Wenn Sie das Tool jedoch mit einer bereits vorhandenen Datei starten, gibt es keine nachfolgenden Erstellungsereignisse und das Tool wird ewig warten.

Es sieht so aus, als müssten Sie ein benutzerdefiniertes Tool implementieren, das zuerst prüft, ob die Datei bereits vorhanden ist, und wenn nicht, mit der Überwachung der Datei beginnt.


Vielen Dank für Ihre Antwort, aber ich frage nach einem bereits erstellten Tool. "Ein benutzerdefiniertes Tool implementieren" ist also keine gültige Antwort. Entschuldigung.
Francisco R

@ ThomasWeller nicht wirklich, nein. Erstens ist dies kein Stackoverflow, sodass jemand, der jemandem sagt, er solle codieren, hier nicht so nützlich ist, nicht einmal auf SO, es sei denn, er gibt den Code an. Und zweitens fragen die Leute oft, wie man etwas macht, was für SU völlig gültig ist. Und die Antwort könnte besagen, dass dies in diesem / jenem Tool möglich ist.
Barlop

0

Verwenden Sie PowerShell, um auf die FileSystemWatcher-API zuzugreifen.

#By BigTeddy 05 September 2011 

#This script uses the .NET FileSystemWatcher class to monitor file events in folder(s). 
#The advantage of this method over using WMI eventing is that this can monitor sub-folders. 
#The -Action parameter can contain any valid Powershell commands.  I have just included two for example. 
#The script can be set to a wildcard filter, and IncludeSubdirectories can be changed to $true. 
#You need not subscribe to all three types of event.  All three are shown for example. 
# Version 1.1 

$folder = 'c:\scripts\test' # Enter the root path you want to monitor. 
$filter = '*.*'  # You can enter a wildcard filter here. 

# In the following line, you can change 'IncludeSubdirectories to $true if required.                           
$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property @{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} 

# Here, all three events are registerd.  You need only subscribe to events that you need: 

Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action { 
$name = $Event.SourceEventArgs.Name 
$changeType = $Event.SourceEventArgs.ChangeType 
$timeStamp = $Event.TimeGenerated 
Write-Host "The file '$name' was $changeType at $timeStamp" -fore green 
Out-File -FilePath c:\scripts\filechange\outlog.txt -Append -InputObject "The file '$name' was $changeType at $timeStamp"} 

Register-ObjectEvent $fsw Deleted -SourceIdentifier FileDeleted -Action { 
$name = $Event.SourceEventArgs.Name 
$changeType = $Event.SourceEventArgs.ChangeType 
$timeStamp = $Event.TimeGenerated 
Write-Host "The file '$name' was $changeType at $timeStamp" -fore red 
Out-File -FilePath c:\scripts\filechange\outlog.txt -Append -InputObject "The file '$name' was $changeType at $timeStamp"} 

Register-ObjectEvent $fsw Changed -SourceIdentifier FileChanged -Action { 
$name = $Event.SourceEventArgs.Name 
$changeType = $Event.SourceEventArgs.ChangeType 
$timeStamp = $Event.TimeGenerated 
Write-Host "The file '$name' was $changeType at $timeStamp" -fore white 
Out-File -FilePath c:\scripts\filechange\outlog.txt -Append -InputObject "The file '$name' was $changeType at $timeStamp"} 

# To stop the monitoring, run the following commands: 
# Unregister-Event FileDeleted 
# Unregister-Event FileCreated 
# Unregister-Event FileChanged

Hier zu finden: https://gallery.technet.microsoft.com/scriptcenter/Powershell-FileSystemWatche-dfd7084b


Eine akzeptable Antwort sollte nicht auf Links von Drittanbietern beruhen, die möglicherweise irgendwann in der Zukunft unterbrochen werden. Können Sie dies korrigieren?
Verdächtiger
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.