1

At times when I'm trying to delete an exe file for one of my processes I get the following error from GetLastError:

Error: 32
The process cannot access the file because it is being used by another process.

Is there a way to find out what's holding a lock on that file using C++ and WinAPIs?

c00000fd
  • 20,994
  • 29
  • 177
  • 400
  • 1
    Is this what you are trying to to: http://stackoverflow.com/questions/1990535/win32-files-locked-for-reading-how-to-find-out-whos-locking-them – Naveen Aug 26 '13 at 07:09
  • @Naveen: Thanks. Btw, nice CodeProject article. I'll need to read it. Just curious, is it also how `Unlocker` unlocks files -- with the use of a device driver? – c00000fd Aug 26 '13 at 07:13
  • @c00000fd: The only reason why you *need* a device driver is to be able to distinguish ordinary files from named pipes without deadlocking. Aside from that, this can all be accomplished from user-mode, although with some difficulty (assuming you have the right permissions). You don't *need* a driver to unlock files -- you could instead inject a thread into another process that closes the handle, for example. Or you can use `DuplicateHandle(..., DUPLICATE_CLOSE_SOURCE)`. But a driver makes it much easier. – user541686 Aug 26 '13 at 07:20
  • @c00000fd: Sorry..I have no idea regarding that. – Naveen Aug 26 '13 at 07:21
  • If you need a signed device driver, I suggest you take a look at the one provided with [Process Hacker](http://processhacker.sourceforge.net/); it's open-source. – user541686 Aug 26 '13 at 07:22
  • @Mehrdad: Hmm. Any links to the code to do that? I also found `IFileIsInUse::GetAppName` from the page that Naveen linked to. There's a Microsoft article how to us it called `FileIsInUse`, but it's literally a mile long. Any idea how to use that method in a few lines of plain C/C++? – c00000fd Aug 26 '13 at 07:23
  • @c00000fd: I don't think `IFileIsInUse` will do what you need, because it requires the file to have been previously registered by the program that opened it. But in any case, you won't be able to do this in "a few lines". Expect at least a couple hundred, probably more. – user541686 Aug 26 '13 at 07:24
  • @Mehrdad: I see, I'm definitely not going into device drivers territory... Damn! – c00000fd Aug 26 '13 at 07:24
  • @c00000fd: For `IFileIsInUse`, see this code I just found on Google: https://gist.github.com/adrianoc/6178111/raw/b203a622f4371db0f1c92f019c4136c5e3d7441a/DumpROT.cpp but yeah I don't think it'll work for what you want. – user541686 Aug 26 '13 at 07:25
  • 1
    @c00000fd: Drivers aren't scary. (These aren't "device" drivers by the way.) You just say `CreateFile("\\.\DriverObjectName")` to open a `HANDLE` to the object they've created, and use `DeviceIoControl` to communicate with them. As long as you're not *writing* the driver (which you don't need to do... Process Hacker already has it written, just use the one provided with it) this is somewhat easy. You just have to make sure you call `CreateService`, etc. appropriately, to create/delete/start/stop the driver at the right times. – user541686 Aug 26 '13 at 07:30
  • @Mehrdad: Thanks. I tried to see what that short github code sample does and I have no clue. It uses IFileIsInUse but it's kinda weird how... Anyway, it's an interesting idea about using the Process Hacker driver. I honestly have no experience doing that. Plus, what is the license to distribute that process hacker driver? – c00000fd Aug 26 '13 at 07:35
  • @c00000fd: I don't remember what the license for the driver is. The rest of the program is GPL. You should ask the author [on the forum](http://processhacker.sourceforge.net/forums/viewforum.php?f=5&sid=34c8697a20f699035c93a4cabde8aec7). – user541686 Aug 26 '13 at 07:40
  • 1
    For a Vista and above solution you can use the [Restart Manager](http://msdn.microsoft.com/en-us/library/windows/desktop/cc948910.aspx). Raymond Chen has a blog entry on the subject: [How do I find out which process has a file open?](http://blogs.msdn.com/b/oldnewthing/archive/2012/02/17/10268840.aspx). – IInspectable Aug 26 '13 at 12:10
  • @IInspectable: Awesome! I didn't know that Restart manager can do that ... doh! :) Hey, can someone sum up all these ideas in an answer. It might be helpful for others. I also learned that one can add `RmShutdown(dwSession, RmForceShutdown, NULL)` to the Raymond's code to close all processes holding a lock. – c00000fd Aug 26 '13 at 19:05

1 Answers1

1

The best solution that works for me can be based on the article suggested by @IInspectable. Check my other reply to your post here.

Community
  • 1
  • 1
ahmd0
  • 16,633
  • 33
  • 137
  • 233