How to determine if a folder ended with C # copying

I have a question: how to determine if a copy of a folder from one place to another has finished?

At the moment, my FileSystemWatcher is triggering several events as soon as the file in the directory is copied. However, I want one event to be fired when all the files in this folder were successfully copied. My code now looks like this:

static void Main(string[] args) { String path = @"D:\Music"; FileSystemWatcher mWatcher = new FileSystemWatcher(); mWatcher.Path = path; mWatcher.NotifyFilter = NotifyFilters.LastAccess; mWatcher.NotifyFilter = mWatcher.NotifyFilter | NotifyFilters.LastWrite; mWatcher.NotifyFilter = mWatcher.NotifyFilter | NotifyFilters.DirectoryName; mWatcher.IncludeSubdirectories = true; mWatcher.Created += new FileSystemEventHandler(mLastChange); mWatcher.Changed += new FileSystemEventHandler(mLastChange); mWatcher.EnableRaisingEvents = true; Console.WriteLine("Watching path: " + path); String exit; while (true) { exit = Console.ReadLine(); if (exit == "exit") break; } } private static void mLastChange(Object sender, FileSystemEventArgs e) { Console.WriteLine(e.ChangeType + " " + e.FullPath); } 
+4
source share
5 answers

Unfortunately, FileSystemWatcher does not tell you when the file will be completed. So your options ...

  • Set timeout after last record when it is assumed that there will be no more changes
  • Ask the recording application to place a lock file of some variety that tells any other program what it did.

After reading your question again ... it doesn't seem like you have control over another application.

Thus, you will need some kind of timeout value, which determines when all records will be executed. Basically create a timer that resets after every file system event ... when it expires, you fire one event that says it is done.

Here is how you could add it to your code ...

 static void Main(string[] args) { Timer.Interval = 5000; // 5 seconds - change to whatever is appropriate Timer.AutoReset = false; Timer.Elapsed += TimeoutDone; String path = @"D:\Music"; FileSystemWatcher mWatcher = new FileSystemWatcher(); mWatcher.Path = path; mWatcher.NotifyFilter = NotifyFilters.LastAccess; mWatcher.NotifyFilter = mWatcher.NotifyFilter | NotifyFilters.LastWrite; mWatcher.NotifyFilter = mWatcher.NotifyFilter | NotifyFilters.DirectoryName; mWatcher.IncludeSubdirectories = true; mWatcher.Created += new FileSystemEventHandler(mLastChange); mWatcher.Changed += new FileSystemEventHandler(mLastChange); mWatcher.EnableRaisingEvents = true; Console.WriteLine("Watching path: " + path); Timer.Start(); String exit; while (true) { exit = Console.ReadLine(); if (exit == "exit") break; } } private static Timer Timer = new Timer(); private static void TimeoutDone(object source, ElapsedEventArgs e) { Console.WriteLine("Timer elapsed!"); } private static void mLastChange(Object sender, FileSystemEventArgs e) { Console.WriteLine(e.ChangeType + " " + e.FullPath); if (Timer != null) { Timer.Stop(); Timer.Start(); } } 
+2
source

This is terribly flabby, but in the past I ran into this problem by creating my own decorator for the FileSystemWatcher class. Inside, it creates a FileSystemWatcher and logs the "Created and Modified" events, wraps them and displays its own created and modified events after the files are finished, similar to this:

 private void Watcher_Changed(Object sender, FileSystemEVentArgs e) { while (true) { FileStream stream; try { stream = File.Open(e.FullPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None); // If this succeeds, the file is finished Changed(); } catch (IOException) { } finally { if (stream != null) stream.Close(); } } } 

Some of them are taken from the answer here . In fact, you should not use an infinite loop. You probably want to add timeouts, sleep between checks, etc., but this is a general idea.

0
source

If the target is a local folder, you can use the file system filter driver to track file creation and file closing events. Knowing when all previously created files will be closed, you will inform that the copying is completed.

0
source

I created a Git repo with a class that extends FileSystemWatcher to trigger events only after the copy is complete.

Download FileSystemSafeWatcher and add it to your project.

Then use it like a regular FileSystemWatcher and track it when events fire.

 var fsw = new FileExamSystemWatcher(file); fsw.EnableRaisingEvents = true; // Add event handlers here fsw.Created += fsw_Created; 
0
source

Unfortunately, there is no ready-made solution. but I developed a simple tricky solution for triggering (copying completed) events.

You must use a timer.

  FileSystemWatcher fsw = new FileSystemWatcher(); string fullPath = ""; DateTime tempTime; fsw.Path = @"C:\temp"; private void startwatching() { timer1.Start(); } fsw.EnableRaisingEvents = true; fsw.Created += Fsw_Created; private void Fsw_Created(object sender, FileSystemEventArgs e) { tempTime = DateTime.Now.AddSeconds(-4); fullPath = e.FullPath; } private void timer1_Tick(object sender, EventArgs e) { if (fullPath!=string.Empty) { timer1.Stop(); if (tempTime >= Directory.GetLastAccessTime(fullPath)) { DirectoryInfo di = new DirectoryInfo(fullPath); listBox1.Items.Add("Folder " + di.Name + " finished copying"); fullPath = string.Empty; } else { tempTime = DateTime.Now; } timer1.Start(); } } 
0
source

Source: https://habr.com/ru/post/1491168/


All Articles