C# FileSystemWatcher在保存文件之前激发-如何;暂停“;过程是什么?
下面是我正在尝试的逻辑代码: 服务监视目录中的.pptx文件。 如果文件已更改,请执行到jpg的转换。然后执行其他任务,这些任务将在以后添加 我使用的是file wather对象,但它会在我打开文件时立即触发,因此我想通过检查文件是否“锁定”来停止进程。我认为“whilelocked”循环可以解决这个问题,但不是。下面是简化的代码原型,我想知道您是否可以看看它,看看我做错了什么,以及/或者是否有更好的方法为生产环境编写这篇文章。pptx文件可以长时间打开C# FileSystemWatcher在保存文件之前激发-如何;暂停“;过程是什么?,c#,multithreading,io,C#,Multithreading,Io,下面是我正在尝试的逻辑代码: 服务监视目录中的.pptx文件。 如果文件已更改,请执行到jpg的转换。然后执行其他任务,这些任务将在以后添加 我使用的是file wather对象,但它会在我打开文件时立即触发,因此我想通过检查文件是否“锁定”来停止进程。我认为“whilelocked”循环可以解决这个问题,但不是。下面是简化的代码原型,我想知道您是否可以看看它,看看我做错了什么,以及/或者是否有更好的方法为生产环境编写这篇文章。pptx文件可以长时间打开 namespace FileWatche
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)以1000毫秒的延迟处理队列,当您收到事件时,停止/启动计时器
- 检查队列中同一文件的多个事件,例如,一个程序可能创建一个文件,然后再次删除它
- Powerpoint与其他Office应用程序一样,创建一个带有
前缀的隐藏临时文件~
- 检查文件修改时间戳。当您第一次注意到文件已更改时,请保存修改时间,并在下次更改文件时与之进行比较
- 您需要设置文件系统监视程序的某个标志属性以获得修改时间更改
希望所有这些都有帮助 是的,FileInfo的LastAccesTime确实显示了时间,而不是当前时间,这正是我想要的。但是,没有跟踪更改的属性。你如何测试它?谢谢。@Risho我不知道你为什么说没有跟踪变化的属性。我正在用示例代码编辑我的答案。我能够监视文件上的更改事件,并且每次修改文件时,时间确实会增加。因为所有fsw方法都是在我单击文件时触发的,而不是在保存文件时触发的。我必须解释文件可能会打开几个小时。@Risho:那不是真的。实际保存文件时,将触发更改的事件。我自己测试了100次。也许您的代码还有其他问题?我感谢您的时间和努力,因为完成这项工作至关重要。但事实并非如此。现在这只是一个控制台应用程序,只要我运行它并打开文件,就会立即触发FileSystemWather更改事件。如果我没有在方法内部设置断点,程序将在修改我的文件之前运行该方法。@SuperJMN,谢谢您的报告。我已经用档案中的副本修复了链接。