繁体   English   中英

FileSystemWatcher在文件保存之前启动-您如何“暂停”该过程?

[英]FileSystemWatcher fires before file is saved - how do you “pause” the process?

这是我尝试代码的逻辑:

服务监视目录中的.pptx文件。 如果文件已更改,请转换为jpg。 然后执行其他任务,稍后将添加。

我正在使用文件存储对象,但是一旦打开文件即会触发,因此我想通过检查文件是否“锁定”来停止该过程。 我以为“锁定时”循环可以解决问题,但是没有。 下面是简化的代码原型,如果您能看一下它,我想表明我在做错什么,和/或是否有更好的方法为生产环境编写代码。 pptx文件可以打开很长时间。

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();
    }
}

}

这是另一个想法:当FileSystemWatcher检测到更改(您说它立即触发文件打开)时,记录文件的LastModifiedTime并继续循环直到文件的LastModifiedTime更改(假定LastModifiedTime仅在保存文件时才写入) -我不知道这实际上是什么时候完成的,然后执行转换为JPG的过程。

编辑

添加应该演示如何跟踪文件修改时间的代码:

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);
    }
}

为了使FileSystemWatcher适用于生产级代码,您需要做大量的逻辑工作。

  • 你要保持事件处理程序很轻,只是队列发生什么事,然后再对其进行处理。

  • 使用计时器(最好使用System.Threading)以1000ms的延迟处理队列,当您收到事件时,停止/启动计时器。

  • 检查队列中是否有同一文件的多个事件,例如,程序可以创建一个文件,然后再次将其删除。

编辑:我只是做了一个快速的Google搜索,发现了一篇文章和示例代码,可以使您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/

编辑2:只是重新阅读您的问题。 上面的建议仍然适用,但是您需要做一些其他事情来解决您的问题:

  • 与其他Office应用程序一样,Powerpoint会创建一个带有~前缀的隐藏临时文件。

  • 检查文件修改时间戳。 当您第一次注意到文件已更改时,请保存修改时间,并在下次文件更改时与它进行比较。

  • 您需要设置文件系统监视程序的一些标志属性来更改修改时间。

希望所有这些对您有帮助...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM