2011-05-05 55 views
2

我試圖創建一個Windows服務,將抓住新文件上傳到目錄,編輯它們並移動到其他目錄。看來我可以複製它們,但不能移動。這是爲什麼?目錄掃描儀Windows服務與FileSystemWatcher

using System; 
using System.ServiceProcess; 
using System.Threading; 
using System.IO; 

namespace ImportService 
{ 
    public class ImportServer : ServiceBase 
    {   
     private System.Diagnostics.EventLog eventLog1; 
     private FileSystemWatcher watcher; 

     public ImportServer() 
     { 
      this.ServiceName = "ImportService"; 

      this.CanHandlePowerEvent = true; 
      this.CanHandleSessionChangeEvent = true; 
      this.CanPauseAndContinue = true; 
      this.CanShutdown = true; 
      this.CanStop = true; 
      this.AutoLog = true;   

      InitializeComponent(); 
      if (!System.Diagnostics.EventLog.SourceExists("ImportServiceLogSource")) 
       System.Diagnostics.EventLog.CreateEventSource("ImportServiceLogSource", "ImportServiceLog"); 
      eventLog1.Source = "ImportServiceLogSource"; 
      eventLog1.Log = "ImportServiceLog"; 
     } 

     public static void Main() 
     { 
      ServiceBase.Run(new ImportServer());    
     }   

     protected override void OnStart(string[] args) 
     { 
      //base.OnStart(args); 

      eventLog1.WriteEntry("service started"); 

      watcher = new FileSystemWatcher(); 
      watcher.Path = "C:\\INPUT\\"; 
      watcher.Filter = "*.jpg"; 
      watcher.EnableRaisingEvents = true; 
      watcher.Created += new FileSystemEventHandler(OnCreated);    
     } 

     private void OnCreated(object sender, FileSystemEventArgs e) 
     { 
      String output_dir = "C:\\OUTPUT\\"; 
      String output_file = Path.Combine(output_dir, e.Name); 
      File.Move(e.FullPath, output_file); 
      // File.Copy() works here 
      eventLog1.WriteEntry("moving file to " + output_file); 
     } 

     protected override void OnStop() 
     {    
      eventLog1.WriteEntry("service stopped"); 
      base.OnStop(); 
     } 

     protected override void OnContinue() 
     { 
      base.OnContinue(); 
     } 

     protected override void OnPause() 
     { 
      base.OnPause(); 
     } 

     private void InitializeComponent() 
     { 
      this.eventLog1 = new System.Diagnostics.EventLog(); 
      ((System.ComponentModel.ISupportInitialize)(this.eventLog1)).BeginInit(); 
      ((System.ComponentModel.ISupportInitialize)(this.eventLog1)).EndInit(); 

     } 
    } 
} 

我也應該保留base.OnStart();等。它真的做什麼?

更新:如何移動在觀察目錄中創建的文件? 文件已在使用異常問題。

+0

好的,找出了自動啓動解決方案。 File.Move()導致一個問題(服務僅檢測到第一個創建/複製的文件,然後崩潰),但仍在處理它。 – yosh 2011-05-05 11:01:46

+0

File.Move(...)拋出什麼異常?此外,base.OnStart()可確保運行ServiceBase的OnStart方法中的任何內容。如果沒有什麼,你不需要叫它。 – 2011-05-05 11:31:15

+0

「文件無法移動,因爲它被另一個進程使用」。什麼樣的條件/計時器會盡快移動文件? – yosh 2011-05-05 11:50:52

回答

2

您將不得不趕上IOException並使線程休眠幾次然後重試。

private void OnCreated(object sender, FileSystemEventArgs e) 
{ 
    String output_dir = "C:\\OUTPUT\\"; 
    String output_file = Path.Combine(output_dir, e.Name); 
    while (true) 
    { 
     try 
     { 
      File.Move(e.FullPath, output_file); 
      break; 
     } 
     catch (IOException) 
     { 
      //sleep for 100 ms 
      System.Threading.Thread.Sleep(100); 
     } 
    }   
    eventLog1.WriteEntry("moving file to " + output_file); 
} 

這就是說,這有很多問題。每隔幾秒鐘就會調用一次定時器事件來查找文件夾中的文件,這樣會更好。如果你得到一個IOException,你就繼續前進。該文件仍然會在下一次迭代中進行處理(假設上傳已完成)。如果我需要的話可以給我一個例子。

+0

謝謝,我之前嘗試過這種方法,但問題是這些文件一直在「使用中」。我也試過這個定時器/線程,但是我有一些問題讓它掃描幾次。當我啓動服務時,它只處理文件夾中的文件。如果你有一個沒有這個問題的例子,我很想去檢查它。 – yosh 2011-05-05 12:51:16

+0

使用進程資源管理器並找出哪些文件具有打開的句柄。您可以搜索相關文件名稱。 http://technet.microsoft.com/en-us/sysinternals/bb896653 – 2011-05-05 13:06:57

+0

好吧,現在我已經爲每個輸入目錄創建了線程,但是他們只在我啓動服務時掃描目錄。這就像'while(started){filepaths [] = Directory.GetFiles(「C:\」);做一點事(); Thread.Sleep(1000)}'。它爲什麼只運行一次? :( – yosh 2011-05-05 14:38:48

0

如果您要避免服務崩潰,則您的OnCreated實施需要處理異常。處理文件時可能會出現很多問題,並且您的服務需要在執行時恢復正常。

這裏的一種可能性是OnCreated事件在編寫新文件的過程完成寫入之前可能觸發,因此嘗試移動文件會引發異常。

+0

是的,現在用try/catch塊來解決這個問題。我得到的例外是「另一個進程使用的文件」。只要上傳完成,我真的很想強制服務來移動文件。既可以本地粘貼到目錄,也可以通過ftp遠程上傳。 – yosh 2011-05-05 11:52:00

0

據我所知,您需要等到文件傳輸完成並且文件關閉後才能移動文件。

這已經在SO上討論過幾次了。例如。 herehere