FileSystemWatcher - 在删除时,复制一个文件

Posted

技术标签:

【中文标题】FileSystemWatcher - 在删除时,复制一个文件【英文标题】:FileSystemWatcher - On Delete, copy a file 【发布时间】:2017-12-14 11:15:18 【问题描述】:

我有一个问题,我正在创建一个 FileWatcher 来监视一个文件夹,并且我正在尝试创建一个从另一个位置复制已删除文件的方法。

这可以使用 FileSystemEventHandler 吗?

或者,在最后一种情况下,我可以使用 FileSystemWatcher 限制文件夹进行更改吗?

谢谢。

【问题讨论】:

您是否尝试实现类似于Windows Protected Files 的东西?如果是这样,我不确定您是否可以在没有 Windows 的情况下做到这一点。如果没有,我没有清楚地理解你的场景。 我有一个包含 3 个文件的文件夹,我想监视该文件夹。如果其中一个文件被删除,我希望文件观察器从其他文件夹复制相同的文件。 是的,这是可能的。你看the docs了吗? 您是说如果正在监视的文件被删除,那么您想从其他地方恢复它吗?因为如果这是问题所在,您是否尝试在 FSW 类上使用 .Deleted 事件? 是的,我已经完成了Microsoft 中的所有代码。但我不能将变量或函数传递给 FileSystemEventArgs。代码:Monitor.Deleted += new FileSystemEventHandler(OnChanged); 【参考方案1】:

您的代码应类似于以下内容:

using System.IO;

//...

const string SourceDirectory = @"\\myServer\share\originalFiles";
private static void OnDeleted (object source, FileSystemEventArgs e)


    //this will help prove if the fsw is being triggered / whether the error's in your copy file piece or due to the trigger not firing
    Debug.WriteLine(e.FullPath);
    Debug.WriteLine(e.ChangeType);

    var filename = e.Name; //NB: Returns path relative to the monitored folder; e.g. if monitoring "c:\demo" and file "c:\demo\something\file.txt" is changed, would return "something\file.txt"
    //var filename = Path.GetFilename(e.FullPath); //if you don't want the above behaviour, given the same scenario this would return "file.txt" instead
    var sourceFilename = Path.Combine(SourceDirectory, filename);

    /* not sure if this is required: see https://github.com/Microsoft/dotnet/issues/437
    while (File.Exists(e.FullPath))  //just in case the delete operation is still in progress when this code's triggered.
        Threading.Thread.Sleep(500);
    
    */

    File.Copy(sourceFilename, e.FullPath);


//...

const string MonitoredDirectory = @"\\myServer\share\watchedFiles\";
public static void Main(string[] args) 
    FileSystemWatcher fsw = new FileSystemWatcher();
    fsw.Path = MonitoredDirectory;
    fsw.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
    //fsw.Filter = "*.xml"; //add something like this if you want to filter on certain file extensions / that sort of thing 
    fsw.OnDeleted += new FileSystemEventHandler(OnDeleted);
    fsw.EnableRaisingEvents = true;
    Console.WriteLine("This monitor will now run until you press 'x' (i.e. as we need to keep the program running to keep the fsw in operation)");
    while(Console.Read() != 'x');

(以上未经测试)

【讨论】:

这行得通吗?在这个事件引发之前文件不是被删除了吗? @ErnodeWeerd 如前所述,未经测试。但是,这应该不是问题;我们不是复制已删除的文件,而是选择“模板”并将其复制到已删除文件的先前位置。唯一的潜在问题与竞争条件有关,即在调用副本时文件可能尚未完全删除;为此,您需要取消注释 while (File.Exists(e.FullPath)) 循环...但是如果在删除和我们的代码运行之间重新创建文件,这可能会导致无限循环;所以需要一个超时来改善/防止这种情况

以上是关于FileSystemWatcher - 在删除时,复制一个文件的主要内容,如果未能解决你的问题,请参考以下文章

使用FileSystemWatcher警告多个文件是否同时更改

C# FileSystemWatcher - 多个事件

关于FileSystemWatcher监听文件创建

Filesystemwatcher 没有在看子目录

FileSystemWatcher用法详解

Powershell FileSystemWatcher - 避免在创建时重复操作