Laden...

Ordner Überwachung mit FileSystemWatcher

Erstellt von Eremit vor 3 Jahren Letzter Beitrag vor 3 Jahren 303 Views
E
Eremit Themenstarter:in
1 Beiträge seit 2021
vor 3 Jahren
Ordner Überwachung mit FileSystemWatcher

Hallo zusammen,
ich bin Oliver und ich habe folgende Problemstellung und möchte dies mit einer kleinen Konsolenanwendung lösen.
Ich muss eine Textdatei in SQL einlesen. Dazu muss ich einen bestimmten Ordner überwachen, ob eine neue Datei vorliegt. Ist das der Fall lass ich einen kleinen Batch laufen. Anschließend geschieht der SQL-Import und der Ordner soll weiter überwacht werden. Und genau da besteht mein Problem die erste Datei, die im Ordner ankommt, wird wie erwartet verarbeitet danach kommt aber eine Fehlermeldung, dass er die aufbereitete Quelldatei, die durch den Batch erzeugt wird, nicht findet. Es wird nicht auf die Überwachung des Ordners gewartet, der dann ein neues Ereignis auslöst.
Zur Veranschaulichung habe ich eine Kurzform der Konsolen Anwendung beigefügt. Da ich neu auf dem Gebiet der C Sharp Programmierung bin hoffe ich das mir Auf diesem Wege jemand helfen kann. Vielen Dank schon mal.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace test5
{
    class Program
    {
        static void Main(string[] args)
        {            
                ////FileSystemWatcher
                FileSystemWatcher FSW;
                Console.WriteLine("Hello World!");
                Console.WriteLine("Ordner überwachen starten");
                // Filesystemwatcher anlegen
                FSW = new FileSystemWatcher();
                // Pfad und Filter festlegen
                FSW.Path = @"C:\sql";
                FSW.Filter = "*.txt";
                // Events definieren
                FSW.Created += new FileSystemEventHandler(FSW_Created);
                
                // Filesystemwatcher aktivieren
                FSW.EnableRaisingEvents = true;
                Console.WriteLine("Listening...");
                Console.WriteLine("(Press any key to exit.)");
                Console.ReadLine();

            void FSW_Created(object sender, FileSystemEventArgs e)
            {
                Console.WriteLine(("Erstellt: " + e.Name));
                Console.WriteLine();
                Console.WriteLine();

                //// Batch für Vorbereitung
                string systemzeit = DateTime.Now.ToString("yyyyMMddHHmmssfff");

                // Datei umbenen
                string path3 = @"c:\sql\" + e.Name;
                string path4 = @"c:\sql\artikel_neu.txt";
                File.Move(path3, path4);

                // Batch ausführen
                //System.Diagnostics.Process.Start(@"C:\sql\replace.bat");
                System.IO.File.Copy(path4, @"c:\sql\artikel_bearbeitet.txt"); // nur zur Veranschaulichung des Batches
                System.IO.File.Delete(path4);

                Console.WriteLine("Batch für die Vorebeitung wurde ausgeführt");
                Console.WriteLine();

                //// StreamReader
                Console.WriteLine("SQL Import wurde ausgeführt");
                Console.WriteLine();

                //// Nachbereitung
                // Datei verschieben
                string path = @"c:\sql\artikel_bearbeitet.txt";
                string path2 = @"c:\sqlarchiv\" + systemzeit + "_" + "artikel_bearbeitet.txt";
                File.Move(path, path2);
                Console.WriteLine("{0} wurde nach verschoben {1}.", path, path2);

                Console.WriteLine("Batch für die Nachebeitung wurde ausgeführt");
                Console.WriteLine();
                
            }

        }
    }
}

16.830 Beiträge seit 2008
vor 3 Jahren

Hi,

also der Quellcode hat einige grundlegende Fehler / unpassende Umsetzungen, zum Beispiel, dass die Event-Verarbeitung im identischen Thread läuft wie die Überwachung selbst.

die durch den Batch erzeugt wird, nicht findet

Dazu können wir wenig sagen ausser, dass Du eigentlich immer bei jedem Dateizugriff prüfen musst, ob eine Datei existiert oder nicht.
Das ist ein Grundlegender Faktor bei der Interaktion mit dem Dateisystem.

Wenn eine Datei nicht gefunden wird dann meistens, weil die Datei nicht existiert.
Wo die Datei wirklich liegt bzw wo gesucht wird, das kannst nur Du selbst prüfen, zB mit [Artikel] Debugger: Wie verwende ich den von Visual Studio?

Das Problem wird aber sein, dass Du einfach Deine Pfade auch völlig "falsch" zusammen baust.

Wenn Du in die Dokumentation von FileSystemEventArgs Klasse (System.IO) schaust, dann siehst Du, dass der vollständige Pfad im Event mitgegeben wird.
Es gibt also keine Notwendigkeit, dass Du im Event selbst nochmal den Quellpfad mit String-Operationen zusammen baust.
Ohnehin sollte man niemals Pfade von Hand zusammen bauen, sondern mit der Pfad Klasse.

Dann hast Du noch so unlogische und vermutlich fatalere Fehler wie


                string path3 = @"c:\sql\" + e.Name;
                string path4 = @"c:\sql\artikel_neu.txt";
                File.Move(path3, path4);

Du nimmst die Quell-Datei im überwachten Ordner, erstellt eine neue Datei im überwachten Ordner mit einem fixen Name.
Wozu führt das: es wird ein neuer Event geworfen, mit der Ziel-Datei als Quell-Datei.

Das hat zur Folge, dass Du Dir eine Endlos-Event-Schleife gebaut hast, weil Du auf selbst erzeugtes Zeug hörst und Du Dir selbst den Prozess neu startest.
Wenn Du mal den Debugger anwirfst, dann solltest Du auch merken, dass hier was nicht stimmen kann.

Also: niemals im überwachten Folder Dateien erstellen, die dem Watch-Pattern entsprechen und Du Dir nen endless Loop baust.

Es wird nicht auf die Überwachung des Ordners gewartet, der dann ein neues Ereignis auslöst.

Das hast Du auch nirgends programmiert. Wenn Du das willst, dann musst Du das entsprechend auch im Code umsetzen 😉

Dann abschließend noch der Hinweis, dass man Zeiten in solch einem Fall besser als UTC speichert und nicht als Systemzeit.
Zeiten sollten Unique sein, was Systemzeiten/ lokalisierte Zeiten nicht sind. Daher sollten Zeiten in Dateien oder in Dateinamen, genauso wie in Datenbanken, sich immer nach UTC richten.

[FAQ] DateTime vs. DateTimeOffset und der Umgang mit Zeiten in .NET