2011-08-26 67 views
6

這裏是我試圖編碼的邏輯:FileSystemWatcher在保存文件之前觸發 - 您如何「暫停」該過程?

服務監視目錄中的.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(); 
    } 
} 

}

回答

2

這裏有一個其他的想法:當FileSystemWatcher的檢測到變化(你說它觸發立即打開該文件時)記錄文件的最後修改時間和不斷循環,直到文件更改的最後修改時間(假設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); 
    } 
} 
+0

是,FileInfo中LastAccesTime dislplays的確他們時間,這不是當前的時間,這就是我想要的。然而,沒有一個屬性可以跟蹤變化。你如何測試?謝謝。 – Risho

+0

@裏索我不知道你爲什麼說沒有財產跟蹤變化。我正在用示例代碼編輯我的答案。我能夠監視文件上的更改事件,並且每次修改文件時,DID的確會增加。 – Icarus

+0

becase的所有fsw_方法火的,當我點擊時不將文件保存的文件。我必須說明文件可能會打開幾個小時的事實。 – Risho

1

有大量邏輯的你需要做的,使FileSystemWatcher的適合生產級代碼。

  • 你要保持事件處理程序很輕,只是隊列東西發生了,再後來處理它。

  • 使用計時器(System.Threading是最好的)以1000毫秒的延遲處理隊列,當您收到事件時,停止/啓動計時器。

  • 檢查隊列中是否有同一文件的多個事件,例如,一個程序可能會創建一個文件,然後再次刪除它。

編輯:我只是做了一個快速谷歌搜索,發現了一篇文章和示例代碼,將讓你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應用程序,創建一個具有~前綴的隱藏臨時文件。

  • 檢查文件修改時間戳。當你第一次注意到一個文件已經改變時,保存修改時間,並在下次文件改變時與之比較。

  • 有一個文件系統觀察,你將需要設置得到修改時間變化的一些標誌財產。

希望這一切可以幫助...

+0

鏈接已損壞。 – SuperJMN

+0

@SuperJMN,謝謝報告。我已經修復了存檔中副本的鏈接。 – Dennis