FileSystemWatcher starts before saving a file - how do you "pause" a process?

Here is the logic I'm trying to code:

The service controls the .pptx file in the directory. If the file has changed, convert to jpg. Then complete other tasks that will be added later.

I use the wather object file, but it fires as soon as I open the file, so I decided to stop the process by checking if the file is locked. I thought a "closed" loop would do the trick, but no. The following is a reduced prototype of the code, and I liked it if you could take a look at it, suggesting what I am doing wrong, and / or if there is a better way to write this for a production environment. The pptx file may be open for a long time.

namespace FileWatcherDemo { public class Program { static void Main(string[] args) { FileSystemWatcher fsWatcher = new FileSystemWatcher(); fsWatcher.Path = @"e:\\"; fsWatcher.NotifyFilter = NotifyFilters.LastWrite; fsWatcher.Filter = "*.pptx"; fsWatcher.Changed += new FileSystemEventHandler(fsWatcher_Changed); //fsWatcher.Created += new FileSystemEventHandler(fsWatcher_Changed); //fsWatcher.Deleted += new FileSystemEventHandler(fsWatcher_Changed); //fsWatcher.Renamed += new RenamedEventHandler(fsWatcher_Changed); fsWatcher.EnableRaisingEvents = true; Console.ReadKey(); } static void fsWatcher_Changed(object sender, FileSystemEventArgs e) { try { while( !IsFileLocked()) { Console.WriteLine("Changed Event Fired"); Microsoft.Office.Interop.PowerPoint.Application app = new Microsoft.Office.Interop.PowerPoint.Application(); Presentation pptPresentation = app.Presentations.Open(@"e:\\HowTo.pptx", MsoTriState.msoFalse, MsoTriState.msoFalse, MsoTriState.msoFalse); pptPresentation.SaveAs(@"e:\\Output", PpSaveAsFileType.ppSaveAsJPG, MsoTriState.msoFalse); pptPresentation.Close(); } } catch (Exception ex) { using (StreamWriter w = File.AppendText(@"e:\\ErrorLog.txt")) { Log(ex.Message.ToString(), w); Log(ex.StackTrace.ToString(), w); w.Close(); } } Console.ReadKey(); } static bool IsFileLocked() { FileStream fs = null; FileInfo file = new FileInfo(@"e:\\HowTo.pptx"); try { fs = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); } catch (IOException) { return true; } finally { if(fs != null) fs.Close(); } return false; } public static void Log(string LogMessage, TextWriter w) { w.Write("\r\nLog Entry: "); w.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(), DateTime.Now.ToLongDateString()); w.WriteLine(" :"); w.WriteLine(" {0}", LogMessage.ToString()); w.WriteLine("------------------------------------------"); w.Flush(); } } 

}

+6
source share
2 answers

Here is another idea: when FileSystemWatcher detects a change (you say that it immediately launches the file), write down the LastModifiedTime of the file and continue the cycle until the LastModifiedTime of the file changes (Assuming that LastModifiedTime will be written only when the file is saved - I don’t know when this is really done), and then follow the process of converting to JPG.

EDIT

Adding code that should demonstrate how to track when a file has been modified:

 class Program { static void Main(string[] args) { Thread t = new Thread(()=> DoTest()); t.Start(); Console.WriteLine("Waiting..."); Console.ReadKey(); } private static void DoTest() { FileSystemWatcher fsw = new FileSystemWatcher("C:\\"); fsw.Filter = "*.txt"; fsw.Changed += new FileSystemEventHandler(fsw_Changed); fsw.Deleted += new FileSystemEventHandler(fsw_Deleted); fsw.Renamed += new RenamedEventHandler(fsw_Renamed); fsw.Created += new FileSystemEventHandler(fsw_Created); fsw.EnableRaisingEvents = true; } static void fsw_Created(object sender, FileSystemEventArgs e) { FileInfo fi = new FileInfo(e.FullPath); Console.WriteLine("File Created: "+e.FullPath); Console.WriteLine("Creation Time: " + fi.CreationTime.ToLongTimeString()); Console.WriteLine("Last Access Time: " + fi.LastAccessTime.ToLongTimeString()); Console.WriteLine("Last Write Time: " + fi.LastWriteTime.ToLongTimeString()); Console.WriteLine("Length: " + fi.Length); } static void fsw_Renamed(object sender, RenamedEventArgs e) { FileInfo fi = new FileInfo(e.FullPath); Console.WriteLine("File Renamed: "+e.FullPath); Console.WriteLine("Creation Time: " + fi.CreationTime.ToLongTimeString()); Console.WriteLine("Access Time: " + fi.LastAccessTime.ToLongTimeString()); Console.WriteLine("Last Write Time: " + fi.LastWriteTime.ToLongTimeString()); Console.WriteLine("Length: " + fi.Length); } static void fsw_Deleted(object sender, FileSystemEventArgs e) { FileInfo fi = new FileInfo(e.FullPath); Console.WriteLine("File Deleted: "+e.FullPath); Console.WriteLine("Creation Time: " + fi.CreationTime.ToLongTimeString()); Console.WriteLine("Last Access Time: " + fi.LastAccessTime.ToLongTimeString()); Console.WriteLine("Last Write Time: " + fi.LastWriteTime.ToLongTimeString()); } static void fsw_Changed(object sender, FileSystemEventArgs e) { FileInfo fi = new FileInfo(e.FullPath); Console.WriteLine("File Changed: "+e.FullPath); Console.WriteLine("Creation Time: " + fi.CreationTime.ToLongTimeString()); Console.WriteLine("Last Access Time: " + fi.LastAccessTime.ToLongTimeString()); Console.WriteLine("Last Write Time: " + fi.LastWriteTime.ToLongTimeString()); Console.WriteLine("Length: " + fi.Length); } } 
+2
source

There is a lot of logic needed to make FileSystemWatcher suitable for production-level code.

  • You want the event handlers to be very light, just the queue, something happened, and then process it later.

  • Use a timer (it is best to use System.Threading) to process the queue with a delay of 1000 ms, when you receive an event, stop / start the timer.

  • Check the queue for several events for the same file, for example. the program can create the file and then delete it again.

Edit: I just browsed Google quickly and found an article and sample code that will deliver you 90%.

http://csharp-codesamples.com/2009/02/file-system-watcher-and-large-file-volumes/

http://web.archive.org/web/20120814142626/http://csharp-codesamples.com/2009/02/file-system-watcher-and-large-file-volumes/

Edit 2: Just re-read your question. The above advice still applies, however there are a few more things you can do to solve your problem:

  • Powerpoint, like other Office applications, creates a hidden temporary file with the ~ prefix.

  • Check file modification timestamps. When you first noticed that the file has changed, save the modification time and compare it with it the next time you change the file.

  • There is some file system observer flag property that you will need to set to change the change time.

Hope all this helps ...

+1
source

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


All Articles