我正在尝试创建一个windows服务,它将抓取上传到目录的新文件,编辑它们并移动到其他目录。似乎我可以复制它们,但不能移动。为什么呢?
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();
等。它到底有什么用?
UPDATE:如何移动在监视目录中创建的文件?文件已在使用异常问题。
你必须捕获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
,你就继续。在下一次迭代中,该文件仍然在那里等待处理(假设上传已经完成)。如果你需要的话,我可以给你举个例子。
如果要避免服务崩溃,您的OnCreated
实现需要处理异常。在处理文件时,很多事情可能会出错,当它们出错时,您的服务需要优雅地恢复。
这里的一种可能性是,在写入新文件的进程完成写入之前,OnCreated
事件可能会触发,因此您尝试移动该文件时会抛出异常。
据我所知,您需要等待文件传输完成并关闭文件,然后才能移动文件。
这已经在SO上讨论过好几次了。如。这里和这里。