I have a FileSystemWatcher listening on a folder. When I try renaming this folder (in Windows Explorer) I get a
The action can't be completed because the folder or a file in it is
open in another program
error.
Commenting out the FileSystemWatcher calls fixes this.
I've tried reproducing the error with a simple program, but haven't been successful so I'm not sure what's going on here. Has anyone encountered anything like this with a FileSystemWatcher? If so - what might be causing it?
More information:
The following seems to be enough to cause the error:
FileSystemWatcher fsw = new FileSystemWatcher(path);
fsw.Deleted += new FileSystemEventHandler(fsw_Deleted);
fsw.EnableRaisingEvents = true;
I can rename files in that folder. And sibling files. I even tried putting a return; as the first line in fsw_Deleted. Still didn't work. As didn't closing Visual Studio, and deleting obj and bin, and running again. And I even tried running the exe file not within VS. Still - no lock if it's not running, Locked if it is.
I've discovered what caused this. There was a second FileSystemWatcher - on a sub directory of the first - which didn't allow renaming the first.
(I'm still surprised, though. A FileSystemWatcher should be "invisible".)
Its going to do that, since your process is looking for files in that folder. What you may want to do is add a handler for fsw.Rename. Then inside that process you should do a RemoveHandler on looking for new files, and then add it back in with the new name of the folder.
Related
I have a problem that I am unable to reproduce in the lab / dev environment.
A beta user is reporting the following error during a file copy.
System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\ProgramData....
The line of code in question is:
Directory.CreateDirectory(path);
Now I'm speculating what is going on here is this. Directory.CreateDirectory hands the operation off to the OS. On my test and dev machines there are plenty of resources and the OS creates the directory instantly.
On the beta users machine it is more resource challenged and it doesn't create the directory for a few milliseconds...perhaps even a full second.
In the meantime my application has moved on and is expecting the folder to be there.
file.CopyTo(path, true);
My first question is if I am connecting the dots properly.
Second question is if so how should I handle?
sleep the app and monitor OS events for the folder created flag and then proceed. This seems to be a complex solution.
Sleep the app. Spin up a new thread that probes for the folder. When it exists kill thread then proceed. Perhaps not a new thread but same idea on main thread?
Any other ideas?
TIA
Your assessment is likely correct. There is probably a delay between when the Directory.CreateDirectory() call returns and when the directory is actually created on the file system. This is discusses in this post here:
Directory.CreateDirectory Latency Issue?
A workaround would be to call Directory.Exists() (MSDN) in a loop just after the call to CreateDirectory(), something like this:
Direcotry.CreateDirectory(path);
int waitCount = 10;
do {
if (Directory.Exists(path))
{
break;
}
Thread.Sleep(100); // sleep 100ms
waitCount--;
if (waitCount <= 0)
{
throw new Exception("Failed to create directory");
}
} while(true);
The snipped is rough, but hopefully you get the idea.
Use the FileSystemWatcher.Created Event to call you back when the directory is created. You will need to watch the parent directory for activity.
msdn sample code:
https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.created(v=vs.110).aspx
Specific question. I've set up a program that watches for changes to a text file with numbers.
FileSystemWatcher mikeWatcher = new FileSystemWatcher();
System.IO.WaitForChangedResult postMike;
string filePath = #"c:\path.txt";
mikeWatcher.Path = Path.GetDirectoryName(filePath);
mikeWatcher.Filter = Path.GetFileName(filePath);
// Wait for change to the file
postMike = mikeWatcher.WaitForChanged(System.IO.WatcherChangeTypes.Changed);
After this the code continues with the process once the WaitForChanged flag gets complete.
...
The issue I'm having is that while the flag is successfully triggered when I manually change the text file and hit save, when the other program (matlab) writes to and saves to that same file, the flag doesn't seem to be triggered.
I've confirmed that it is indeed the same file being changed (Path is correct) and that the change is registered in the "last modified date". Also, it does appear that the matlab process is closing the text file after saving so its not a release issue, I don't think.
Any thoughts or advice? It'd be easiest for me to change my c# code then the matlab code. All suggestions welcome!
The solution here is to stop using FileSystemWatcher, and instead use a timer to scan the directory for changes.
I have tried to use FileSystemWatcher in two projects and in both cases I found it too unreliable. It would miss some events, delay some events, and report some events twice. I gave up, and haven't used it since.
This answer may not be popular but I'm convinced that the only correct way to use FileSystemWatcher is in comments, like this:
// Tried FileSystemWatcher, but it was far too unreliable.
I think the problem is that it's possible that matlab deletes the file and creates new one with exactly a same name so the file ends up not being changed but newly created. You should trap Deleted and Created events also, not changed only.
Try the code from this example: http://msdn.microsoft.com/en-us/library/t6xf43e0(v=vs.110).aspx
I had the exact same problem and solved it by setting FW.EnableRaisingEvents = true;.
Strange because I don't use the events but it works.
For a project, I needed some FileSystemWatcher on directories. But I got a weird issue : after having launch the app, I can choose the directories where I want to put FileSystemWatcher; if the explorer.exe isn't open when I start to raise events in a directory, I can open it to do stuff in the watched directory. In this case, handlers are fired, and all works perfectly.
Let's imagine I let the explorer.exe open, and I put a FileSystemWatcher in another directory via my app. From this point, I can't modify anything in this second directory : when I modify / rename a file (there's no error during creation of files. EDIT : and I can modify the new file, change his name, etc...), Windows (note this is not the application, but the OS) throws me an error which means "the process can't access this file because of another process accessing it right now".
Does someone have any idea about this, please ?
EDIT : okay, I'm dumb. I just forgot to close a stream...
I'm getting a very intermittent "directory not empty" error trying to delete a directory from c# code but when I look, the directory seems to be empty.
The actual scenario is this: process A invokes process B using a synchronous .Net remoting call, process B deletes the files from the directory and then returns to process A which deletes the directory itself. The disk is a locally attached NTFS Disk (probably SATA).
I'm wondering if there's a possible race Condition with NTFS when you have two processes cooperating in this way, where process B's delete calls have not been completely flushed to the file system?
Of course the more obvious answer is that the directory was genuinely not empty at the time and something else emptied it before I looked at it, but I don't see how this could happen in my current application because there's no other process which would delete the files.
Sure, deleting directories is a perilous adventure on a multi-tasking operating system. You always have the risk that another process has a file opened. Failure to delete the directory in your scenario has two primary reasons:
Particularly trouble-some are the kind of processes that opens the file in a way that does not prevent you from deleting the file but still makes deleting the directory fail with this error. Search indexers and anti-malware fit this category. They'll open the file with delete sharing, FileShare.Delete in a .NET program. Deleting the file works fine. But the file won't disappear until they close the file handle. So you can't delete the directory until they do.
Very hard to diagnose is a process that has the directory selected as its current working directory. Environment.CurrentDirectory in a .NET program. Explorer tends to trigger this, just looking at the directory is enough to prevent it from getting deleted.
These mishaps occur totally outside of your control. You will need to deal with them, catching the exception is required. Little you can do by try again later, there is however no upper limit on how long you'll have to wait. Renaming the directory and giving it a "trash" name is a good strategy. Note how the recycle bin in Windows essentially follows this scenario, good for more than just recycling :)
I have some code that I wrote to basically clear out the directory every time the program runs through this point. I didn't want to bother enumerating files. If this is a bad way to do this, please tell me.
My main question, however, is about how to deal with the following: one of the files in the folder appears to be in use when it is most certainly not. The program runs on a ButtonClick event, and it exploded the first four or five times, but it worked after I confirmed that nobody was using the file on the server. There is only one person besides myself that would have been using it, and he confirmed that there was nothing running on his side that would be touching the file. Any ideas for what would cause this error/how to avoid it/how to handle it?
I am also having trouble reproducing the error...
string directory = #"\\server\directory\folder\";
DirectoryInfo di = new DirectoryInfo(directory);
if (di.Exists)
di.Delete(true);
Directory.CreateDirectory(directory);
If you are using Windows XP, this may help : http://msdn.microsoft.com/en-us/library/dd997370.aspx#remove_open_handles
Just an extract from the top of this page :
"If you are running Windows XP or earlier, a delete operation on a file or directory that follows an enumeration could fail if there is an open handle that remains on one of the enumerated directories or files."
You may also use a software like Unlocker to identify the process locking your file.
If the file is in use, then someone is most certainly using it. :)
If you can access the server the files reside on, you can use a tool such as Process Explorer to find out which process has opened the file.