I'm looking for a way to delete a file which is locked by another process using C#. I suspect the method must be able to find which process is locking the file (perhaps by tracking the handles, although I'm not sure how to do this in C#) then close that process before being able to complete the file delete using File.Delete()
.
Killing other processes is not a healthy thing to do. If your scenario involves something like uninstallation, you could use the
MoveFileEx
API function to mark the file for deletion upon next reboot.If it appears that you really need to delete a file in use by another process, I'd recommend re-considering the actual problem before considering any solutions.
The typical method is as follows. You've said you want to do this in C# so here goes...
Essentially: the way to unlock a "locked" file is to inject a DLL file into the offending process's address space and close it yourself. You can do this using native or managed code. No matter what, you're going to need a small amount of native code or at least P/Invoke into the same.
Helpful links:
Good luck!
If you want to do it programatically. I'm not sure... and I'd really recommend against it. If you're just troubleshooting stuff on your own machine, SysInternals Process Explorer can help you
Run it, use the Find Handle command (I think it's either in the find or handle menu), and search for the name of your file. Once the handle(s) is found, you can forcibly close them.
You can then delete the file and so on.
Beware, doing this may cause the program which owns the handles to behave strangely, as you've just pulled the proverbial rug out from under it, but it works well when you are debugging your own errant code, or when visual studio / windows explorer is being crap and not releasing file handles even though you told them to close the file ages ago... sigh :-)
You can use this program, Handle, to find which process has the lock on your file. It's a command-line tool, so I guess you use the output from that... I'm not sure about finding it programmatically.
If deleting the file can wait, you could specify it for deletion when your computer next starts up:
Start
REGEDT32 (W2K)
orREGEDIT (WXP)
and navigate to:W2K and WXP
W2K:
Edit
Add Value...
Data Type:
REG_MULTI_SZ
Value Name:
PendingFileRenameOperations
OK
WXP:
Edit
New
Multi-String Value
enter
PendingFileRenameOperations
In the Data area, enter
"\??\" + filename
to be deleted. LFNs may be entered without being embedded in quotes. To deleteC:\Long Directory Name\Long File Name.exe
, enter the following data:Then press OK.
The "destination file name" is a null (zero) string. It is entered as follows:
W2K:
Edit
Binary
select Data Format: Hex
click at the end of the hex string
enter 0000 (four zeros)
OK
WXP:
Right-click the value
choose "Modify Binary Data"
click at the end of the hex string
enter 0000 (four zeros)
OK
Close
REGEDT32/REGEDIT
and reboot to delete the file.(Shamelessly stolen from some random forum, for posterity's sake.)
Using Orion Edwards advice I downloaded the Sysinternals Process Explorer which in turn allowed me to discover that the file I was having difficulties deleting was in fact being held not by the
Excel.Applications
object I thought, but rather the fact that my C# code send mail code had created an Attachment object that left a handle to this file open.Once I saw this, I quite simple called on the dispose method of the Attachment object, and the handle was released.
The Sysinternals explorer allowed me to discover this used in conjunction with the Visual Studio 2005 debugger.
I highly recommend this tool!
Oh, one big hack I employed years ago, is that Windows won't let you delete files, but it does let you move them.
Pseudo-sort-of-code:
When the applications restarted (note we didn't need to reboot the machine), they loaded the new
mfc42.dll
, and all was well. That, coupled withPendingFileOperations
to delete the old one the next time the whole system restarted, worked pretty well.This looks promising. A way of killing the file handle....
http://www.timstall.com/2009/02/killing-file-handles-but-not-process.html
You can use code that you supply the full file path to, and it will return a
List<Processes>
of anything locking that file:Then, iterate the list of processes and close them and delete the files:
And depending on if the file is on the local computer:
or a network computer:
References:
How do I find out which process is locking a file using .NET?
Delete a directory where someone has opened a file