我有一个C#windows服务正在查看文件夹。看起来如果使用传统的Windows文件名结构创建文件,一切都很好,例如foo.zip。但随后还有一个那些讨厌命名文件的讨厌的unix人:foo.bar.11-10-2013.zip。
我的程序中的文件监视器永远不会看到此文件。没有过滤器设置,因此它默认为*.*
。
如果我重命名文件以删除点并用下划线替换它们,文件观察者会看到该文件。
我尝试使用谷歌搜索答案,但我的另一个问题是我不确定如何陈述问题 - 我们称之为多个扩展或多个点还是多个时段?所有这些都失去了无益的结果。
所以我的问题:是否可以设置一个文件监视器来检测带有多个点扩展名的linux样式文件名?如果您碰巧知道"多点文件扩展名"的正式术语,我很想知道它们的名称。
答案 0 :(得分:0)
我已经确定答案是你不能,至少在没有大量工作的情况下。我考虑了一个计时器,每隔几秒重命名一个多点文件,但这看起来很破旧。
创建文件时,我将文件观察器设置为触发 - 这是将控件拖到设计图面时获得的结果。
我更改了事件以检测更改,并按尺寸过滤。似乎。排除"多点"文件扩展名,为什么不呢? foo.bar.blah.zip不适合。模式。我们需要的是类似蚁的文件模式描述符(因为没有人提供更好的术语:-),但那些似乎不会通过文档得到支持。
通过让它监视文件大小的变化似乎在创建文件时(从零到某些东西)触发,这对我来说已经足够了。一旦我知道该文件存在,无论控件的过滤器如何,我都可以得到它的名字。
答案 1 :(得分:0)
我昨晚发布的答案没有通过回归测试。我得到了混合结果和文件系统观察者的不同过滤器设置,偶尔会丢失不可接受的文件。有很多关于网络共享问题的文章,但我认为这意味着观察者正在观看映射到不同计算机的网络共享,而不是正在观看的目录本身就是运行该服务的同一台机器上的网络共享。可能延迟是我的一些误操作的一个因素,但即使在本地,该组件似乎也不能识别多点文件名。
由于这是一项服务,我们已经有了一种方法来检测服务启动时已存在的任何文件。这种方法有效并且不依赖于组件。所以最优雅的解决方案是简单地将代码放在计时器上。以下是该课程的相关部分(即此片段不是为了复制/粘贴准备而设计的,只是为了说明我是如何解决问题的)。不要让FTP绰号让你偏离正轨 - 它实际上只是在观看一个可能会或可能不会映射到FTP服务器的共享文件夹。
using System.Collections.Generic;
using Timer = System.Timers.Timer;
public partial class VsiFtpManager : ServiceBase
{
private Timer _searchTimer;
private Queue<string> _filesToProcess;
private string _ftpRoot; //this is set elsewhere from the registry
protected override void OnStart(string[] args)
{
//process any files that are already there when the service starts
LoadExistingFtpFiles();
//Handle new files
_searchTimer = new Timer(10000);
_searchTimer.Elapsed += LoadExistingFtpFiles;
}
//convenience overload to allow this to handle timer events
private void LoadExistingFtpFiles(object source, ElapsedEventArgs evtArgs)
{
LoadExistingFtpFiles();
}
private void LoadExistingFtpFiles()
{
_searchTimer.Stop();
var di = new DirectoryInfo(_ftpRoot);
FileInfo[] fileInfos = di.GetFiles("*.*", SearchOption.AllDirectories);
foreach (FileInfo fi in fileInfos.Where(fi => fi != null))
{
if (fi.Extension != "processed" && !_filesToProcess.Contains(fi.FullName))
{
LogHelper.BroadcastLogMessage("INFO: File " + fi.Name + " was uploaded.", EventLogEntryType.Information);
_filesToProcess.Enqueue(fi.FullName);
LogHelper.BroadcastLogMessage("File received: " + fi.Name, EventLogEntryType.Information);
}
}
_searchTimer.Start();
}
}
你看不到的部分,这超出了我的问题的范围,本质上是一个针对队列_filesToProcess运行的协同例程,它处理文件然后将它们重命名为扩展名为.processed。
所以我的最终答案是:我的研究,通过自动回归测试证实,显示文件系统观察器对于我的用例是不可靠的,这需要我处理复制到文件夹中的文件。其中一些文件来自Unix系统,因此可能有非Windows文件名。使用.net附带的文件系统观察程序组件无法可靠地检测名称中带有多个点的unix样式文件名称。
我用简单的轮询机制替换了文件系统观察器。执行速度明显慢但可靠,这是我的主要目标。整体解决方案减少了我的代码行,虽然微不足道,并删除了我在服务设计界面上的唯一组件,我考虑奖金是因为我自己可能有特殊的偏好。