-1

I have a C# windows service watching a folder. It seems like if files are created using the traditional windows file name structure, everything is fine, e.g. foo.zip. But then along comes one of those pesky unix people who name their files: foo.bar.11-10-2013.zip.

File Watcher in my program never sees this file. There is no filter set, so it is defaulting to *.*.

If I rename the file to remove the dots and replace them with underscores, the file watcher sees the file.

I tried googling an answer but my other problem is I'm not sure how to state the question - do we call it multiple extensions or multiple dots or multiple periods? All of these returned unhelpful results.

So my question: Is it possible to set up a file watcher to detect linux style file names with multiple dot extensions on it? And if you happen to know a formal term for "multi-dot file extensions", I'd love to know what they are called.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
Bruce Van Horn
  • 613
  • 2
  • 6
  • 14
  • 4
    Can you show relevant code? Also, see [docs](http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.filter(v=vs.110).aspx): _"To watch changes in **all files**, set the Filter property to an empty string ("")."_, although later it is claimed "" and "`*.*`" both watch for all files. – CodeCaster Nov 10 '14 at 22:43
  • When you say "I have a C# windows service watching a folder", do you mean that this is a program someone else wrote, or you wrote it? If you wrote it, you may want to post some of your code. Also what do you mean by 'watching' a folder? – TheBlindSpring Nov 10 '14 at 22:46
  • I wrote it. Posting code is irrelevant - i'm trying to figure out how to fire an event, not debug the contents of the method handler which is generated by visual studio. I have consulted the file system watcher class documentation and it does not cover anything regarding non-windows extensions - it just says star dot star or an empty string (which auto fills star dot star in the inspector) covers all files but it clearly doesn't. – Bruce Van Horn Nov 10 '14 at 22:58
  • Not sure I understand the down-vote? Its a good question and nobody else had a solution. Is it b/c I didn't post code? Visual Studio generates that code, not me. I figured everybody had seen it before. – Bruce Van Horn Nov 10 '14 at 23:33
  • 1
    Possibly the problem is with the semantics of what "*.*" means on the different file systems. As I recall, both Windows and Linux will treat a single star (i.e. "*") to mean "all files." You might give that a try. – Jim Mischel Nov 11 '14 at 00:01
  • 1
    The code is not irrelevant. Any sample copied from MSDN or this site works with filenames with multiple dots. The problem is in either your code, your platform or your filesystem. So the answer to your question _"Is it possible to set up a FileSystemWatcher to detect file names with multiple dots in them?"_ is _"Yes"_, and that is not the question you should be asking. – CodeCaster Nov 11 '14 at 09:22

2 Answers2

0

I've decided the answer is that you can't, at least not without a lot of work. I pondered a timer that renames multi-dot files every few seconds, but that seems shabby.

I had the file watcher set to fire when files are created - which is what you get when you drag the control on to the design surface.

I changed the event to detect changes, and I filtered on size. It seems that . precludes "multi-dot" file extensions, and why wouldn't it? foo.bar.blah.zip doesn't fit the . pattern. What we need are ant-like file pattern descriptors (since nobody offered up a better term :-), but those don't seem to be supported via the documentation.

By having it watch for changes in file sizes seems to fire when files are created (going from zero to something) which is good enough for me. Once I know the file is there, I can get its name regardless of the control's filter.

Bruce Van Horn
  • 613
  • 2
  • 6
  • 14
  • look at this posting I miss understood your question looks like someone else on StackOverflow.com was asking something similar http://stackoverflow.com/questions/11306302/filesystemwatcher-with-samba-on-linux – MethodMan Nov 10 '14 at 23:20
  • Thanks. That was useful, but not exactly my problem. It seems like they were monitoring a share and I'm not. They actually got an error message (useful) but I don't -- the event handlers simply don't fire, we miss processing files, and my boss gets cranky. BUT, it made me think about the problem a little bit differently and I have an easy way to account for any missing event fires, now that they actually are firing, I merely need to invoke it periodically. – Bruce Van Horn Nov 10 '14 at 23:28
  • Sounds good..try to refactor it without using full functionality I am curious to learn what the final work around would be .. since I am use to doing this only on a windows system. – MethodMan Nov 10 '14 at 23:31
  • This is a windows system. But sometimes I get files from Unix users. – Bruce Van Horn Nov 10 '14 at 23:34
  • are you usung *.* filter also what type of file extension logic are you doing in regards to Linux files compared to the windows extensions.. can you show some code ..? – MethodMan Nov 10 '14 at 23:37
0

The answer I posted last night didn't pass regression testing. I got mixed results and file system watcher's different filter settings, and it occasionally missed files which is unacceptable. There are lots of articles on problems with network shares but I take that to mean the watcher is watching a network share mapped to a different computer, not that the directory being watched is itself a network share on the same machine where the service is running. It is possible latency is a factor in some of my mis-fires, but even locally, the component does not seem to recognize multi-dot files names.

Since this is a service, we already had a method to detect any files already present when the service started. This method worked and had no reliance on the component. So the most elegant solution was to simply put that code on a timer. Below are the relevant parts of the class (i.e. this snippet isn't designed to be copy / paste ready, only to show how I solved the problem). Don't let the FTP moniker throw you off course - it is really just watching a shared folder which might or might not be mapped to an FTP server.

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();

    }
}

The part you don't see, which is beyond the scope of my question, is essentially a co-routine running against the queue _filesToProcess which processes the files then renames them to have an extension of .processed.

So my final answer: My research, borne out by automated regression testing, showed file system watcher to be unreliable for my use case, which requires me to process files copied into a folder. Some of these files will come from Unix systems and so may have non-windows file names. The file system watcher component shipping with .net cannot reliably detect unix style files names bearing multiple dots within the name.

I replaced the file system watcher with a simple polling mechanism. The execution is significantly slower but reliable, which is my main objective. The overall solution reduced my lines of code, albeit insignificantly, and removed my only component on the design surface of the service, both of which I consider bonuses owing to my own possibly peculiar preferences.

Bruce Van Horn
  • 613
  • 2
  • 6
  • 14