Reputation: 21704
I'm writing a windows service that might delete a file at some point. Because the service is dealing with regular file IO it's possible that a file can be in use during deletion.
Currently I'm trying to delete and react later when an exception happens. Code looks something like this:
try
{
File.Delete(file);
Status = ResponseStatus.Ok;
}
catch (IOException e)
{
Status = ResponseStatus.FileInUse;
}
finally
{
return Status;
}
How can I determine if a file in use without using an exception?
Upvotes: 5
Views: 3168
Reputation: 754565
Expanding on Richie's correct answer
When working with the file system you can never reliably if an operation will succeed. All you can do is try an operation and check to see if it did succeed.
The file system is a moving target which you have no control over. Any number of external and other user events can influence the file system outside of your control. In many ways it's like multi-threaded programming where no synchronization is possible. Whenever you see code like the following, there is a subtle bug
if (File.SomeTypeOfCheck(somePath) {
File.DoSomeOperation(somePath);
}
Upvotes: 3
Reputation: 57892
As Richie says, catching the exception is probably the best approach here.
But what if you want to delete 10 files, and you don't want it to fail half way through? You really need some way of guarding the overall transaction. So it is useful to be able to passively check if a file is in use. You can determine if a file is in use (or read only, which also renders it undeletable) by simply attempting to open it for writing (and then if you succeed, closing it immediately). This doesn't in itself guarantee that a subsequent attempt at deletion will succeed though.
Other approaches that could work would be: - move/rename the file(s) before deletion (put them somewhere safe so you know they can't subsequently be opened by another process), so that you can "undo" the transaction if any of the individual move operations fails. - catch the exception and queue up a future attempt to delete the file (either in your own program, or you can mark a file for automatic deletion by Windows on the next reboot)
Upvotes: 4
Reputation: 185593
If you simply want to test if the delete was successful without catching an exception, you just need to declare a P/Invoke for the DeleteFile
function.
[DLLImport("Kernel32.dll", SetLastError = true)]
public static extern bool DeleteFile(string fileName);
This will return true
if the delete was successful and false
if it was not. If you want the specific error code, you can call Marshal.GetLastWin32Error()
Upvotes: 3
Reputation: 281385
There's no point in trying to detect up front whether the file is in use - what if someone opens the file between your detection code and your deletion code? You're still going to need your existing code to cope with that case.
The code you already have is exactly the right way to do this.
Upvotes: 13