Filesystemwatcher to Watch Unc Path

FileSystemWatcher to watch UNC path

I just tried this:

var _watcher = new FileSystemWatcher();
_watcher.Path = @"\\10.31.2.221\shared\";
_watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;
_watcher.Filter = "*.txt";
_watcher.Created += new FileSystemEventHandler((x, y) =>Console.WriteLine("Created"));
_watcher.Error += new ErrorEventHandler( (x, y) =>Console.WriteLine("Error"));
_watcher.EnableRaisingEvents = true;
Console.ReadKey();

That works without problems, however i replicated your exception just when:

  • The running user doesn't have permissions to read the remote folder.
  • The remote folder doesn't exist.

Your problem surely is related with permissions, I think that the running user doesn't have the permissions needed.

Another thing that you can try is map the remote folder to one local.

Execute this in the cmd:

NET USE Z: \\server2\Secondary\temp\watch_folder /user:Domain\UserName Password

Then in your code:

_watcher.Path = @"Z:\";

FileSystemWatcher Fails to access network drive

I have projects using the FileSystemWatcher object monitoring UNC paths without any issues.

My guess from looking at your code example may be that you are pointing the watcher at the root share of the server (//servername/) which may not be a valid file system share? I know it returns things like printers, scheduled tasks, etc. in windows explorer.

Try pointing the watcher to a share beneath the root - something like //servername/c$/ would be a good test example if you have remote administrative rights on the server.

C# FileSystemWatcher watch changes on network drive which is only done by current system

FileSystemWatcher may notify you that something happened, and you might also be able to deduce what happened, but don't count on it. It's a quite limited and unreliable component in my (and others') experience. So if there is any chance of even moderate contention on the target folder I would use some kind of polling solution instead of file watcher.

That said, it won't tell you who did the change. Once you have deduced what has changed, you need to take additional steps for the "who" part. The filesystem stores quite sparse info, you won't find any source machine info. You could try mapping the fileshares that create these changes with different users, as you may deduce the modifying system from that:
Finding the user who modified the shared drive folder files.

If that is not an option, other solutions are much more complicated.

If you have access to the server hosting Z: you could turn on the file audit log for that resource and deduce who the machine was from the event log (event ids 4663 / 5145). The source machine name will be logged in this case. Should be a breeze to enable it if it's a windows server (Directory properties/security/advanced/audit), but reading and synchronizing logs is more complicated.

If none of the solutions above is possible, you may be able to implement a user-space filesystem to proxy your file share, using something like dokan. Source processes would map to your application instead of the fileshare, that way you could raise your own events or just write a detailed audit log to a database or whatever, and then you forward the actual commands to the fileshare. Very expensive and non-trivial solution though. But probably very fun.

FileSystemWatcher reports file available on network share but file cannot be found

The FileSystemWatcher has a bad reputation, but actually, it is not that bad...

1.)

Your code sample does not compile. I tried this:

 FileSystemWatcher fileWatcher = new FileSystemWatcher();
fileWatcher.Path = "X:\\temp";
fileWatcher.Filter = "test.txt";
fileWatcher.EnableRaisingEvents = true;
fileWatcher.IncludeSubdirectories = false;

var res = fileWatcher.WaitForChanged(WatcherChangeTypes.Changed |
WatcherChangeTypes.Created, 20000);
if (!res.TimedOut)
{
FileInfo fi = new FileInfo(Path.Combine(fileWatcher.Path, res.Name));

using (FileStream stream = fi.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
{
byte[] buf = new byte[stream.Length];

stream.Read(buf, 0, (int)stream.Length);
}

Console.WriteLine("read ok");
}
else
{
Console.WriteLine("time out");
}

I tested this where X: is a SMB share. It worked without problems (for me, see below).

But:

You should open / read the file with retries (sleeping for 100 ms after every unsuccessfully open). This is because you may run into a situation where the FileSystemWatcher detects a file, but the move (or another write operation) has not yet ended, so you have to wait until the file create / mover is really ready.

Or you do do not wait for the "real" file but for a flag file which the file move task creates after closing the "real" file.

2.)

Could it be that the move task did not close the file correctly?

3.)

Some years ago I had some tools (written in perl) where one script created a flag file and another script waited for it.

I had some nasty problems on a SMB 2 share. I found out that this was due to SMB caching.

See

https://bogner.sh/2014/10/how-to-disable-smb-client-side-caching/

File open fails initially when trying to open a file located on a win2k8 share but eventually can succeeed

https://technet.microsoft.com/en-us/library/ff686200.aspx

Try this (on the client):

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\LanmanWorkstation\Parameters]

"DirectoryCacheLifetime"=dword:00000000
"FileNotFoundCacheLifetime"=dword:00000000

Save this as disablecache.reg and run regedit disablecache.reg

Then reboot.

FileSystemWatcher.Path Exception for Network Shared Drive

Drive letter mappings are a per-interactive login setting. The exception is telling you the truth, T:\INFORMATION TECHNOLOGY\bu indeed does not exist because for sessions other than your own session (for example the session 0 that the service runs under) the drive T:\ does not get mapped anywhere. The reason it works when you debug is because when you debug you are likely running the service inside your own session instead of inside session 0.

A similar problem happens when you try to access a mapped drive from a program launched from a UAC prompt because the UAC user is considered a "different user".

Possible further reading for potential workarounds "Map a network drive to be used by a service"

System.IO.FileSystemWatcher to monitor a network-server folder - Performance considerations

From a server load point of view, using the IO.FileSystemWatcher for remote change notifications in the scenario you describe is probably the most efficient method possible. It uses the FindFirstChangeNotification and ReadDirectoryChangesW Win32 API functions internally, which in turn communicate with the network redirector in an optimized way (assuming standard Windows networking: if a third-party redirector is used, and it doesn't support the required functionality, things won't work at all). The .NET wrapper also uses async I/O and everything, further assuring maximum efficiency.

The only problem with this solution is that it's not very reliable. Other than having to deal with network connections going away temporarily (which isn't too much of a problem, since IO.FileSystemWatcher will fire an error event in this case which you can handle), the underlying mechanism has certain fundamental limitations. From the MSDN documentation for the Win32 API functions:

  • ReadDirectoryChangesW fails with ERROR_INVALID_PARAMETER when the buffer length is greater than 64 KB and the application is monitoring a directory over the network. This is due to a packet size limitation with the underlying file sharing protocols

  • Notifications may not be returned when calling FindFirstChangeNotification for a remote file system

In other words: under high load (when you would need a large buffer) or, worse, under random unspecified circumstances, you may not get the notifications you expect. This is even an issue with local file system watchers, but it's much more of a problem over the network. Another question here on SO details the inherent reliability problems with the API in a bit more detail.

When using file system watchers, your application should be able to deal with these limitations. For example:

  • If the files you're looking for have sequence numbers, store the last sequence number you got notified about, so you can look for 'gaps' on future notifications and process the files for which you didn't get notified;

  • On receiving a notification, always do a full directory scan. This may sound really bad, but since the scan is event-driven, it's still much more efficient than dumb polling. Also, as long as you keep the total number of files in a single directory, as well as the number of directories to scan, under a thousand or so, the impact of this operation on performance should be pretty minimal anyway.

Setting up multiple listeners is something you should avoid as much as possible: if anything, this will make things even less reliable...

Anyway, if you absolutely have to use file system watchers, things can work OK as long as you're aware of the limitations, and don't expect 1:1 notification for every file modified/created.

So, if you have other options (essentially, having the process writing the files notify you in a non-file system based way: any regular RPC method will be an improvement...), those are definitely worth looking into from a reliability point of view.

FileSystemWatcher() problem when monitoring mapped UNC

My solution to the problem was to leave the FileSystemWatcher() and create my own little watcher. It's very simple, but the only thing I wanted to watch was when the file was rewritten and then perform some action.

This is basically what I do (removed try/catch and some invoking of other threads):

System.Threading.Timer tFileWatcher;
private string fileTime1 = "";
private string fileTime2 = "";
//
private void Form1_Load(object sender, EventArgs e)
{
tFileWatcher = new System.Threading.Timer(ComputeBoundOp2, 0, 0, 500);
fileTime1 = File.GetLastWriteTime(fileInfo).ToFileTime().ToString();
fileTime2 = File.GetLastWriteTime(fileInfo).ToFileTime().ToString();
}

private void ComputeBoundOp2(Object state)
{
fileTime2 = File.GetLastWriteTime(fileInfo).ToFileTime().ToString();

if (fileTime1 != fileTime2)
{
//Do something
}
}

How to use FileSystemWatcher in Windows service

Problem was in account, under which was service started. For FileSystemWatcher to correctly watch changes on Samba network share, I used Administrator account from domain.



Related Topics



Leave a reply



Submit