views:

100

answers:

4

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?

+2  A: 

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

Adam Robinson
+13  A: 

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.

RichieHindle
+3  A: 

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)

Jason Williams
+1: Good points.
RichieHindle
+1. It's good to keep it in mind. However, it doesn't apply in my case. The service is going to delete one file at a time.
Vadim
+3  A: 

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);
}
JaredPar