Vadim
Vadim

Reputation: 21704

How to determine that a file is in use before deletion?

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

Answers (4)

JaredPar
JaredPar

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

Jason Williams
Jason Williams

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

Adam Robinson
Adam Robinson

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

RichieHindle
RichieHindle

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

Related Questions