Determining what Processes Are Locking a File

February 23, 2014 - .NET, C#

Recently, a mysterious bug cropped up in one of the programs for which I had most of the responsibility. In this case the bug was a strange “The Program cannot access the specified file because it is in use by another process”

One particularly helpful trait to discovering the cause was that exceptions of this nature are actually logged to the Database, so I was able to determine with some accuracy where the exception was occurring. This was in an “Updater” program; the Exception was occurring when it tried to launch the installer it just finished downloading.

To me that didn’t make a whole lot of sense. I was unable to reproduce the error very often and when I Did I got the exception when the Updater attempted to download to a temporary file that was still in use (which I worked around anyway by attempting to find a filename that wasn’t present at all).

My suspicion is that when the Update Application finishes downloading the file, a Anti-virus program is accessing it on the machines with the issue. The problem appears to only occur for the larger updates, which still seems reasonable with this theory since larger updates would take longer to scan. Also, an AV program typically takes an exclusive lock on items it is scanning while it scans.

Even so, it is still only a guess. The only way to confirm it would be to somehow figure out and keep track of what other program(s) are using the file to try to figure out what is locking it.

On Windows XP, we would be out of luck- at least for any simple solution. It would certainly be possible to add this feature but the advanced memory spelunking Would be a pain- and it would require the use of subject-to-change functions like ntQuerySystemInformation or even a Driver, which is probably going a bit far.

Thankfully, Vista, 7, and 8 have a feature called a “Restart Manager”. The Restart Manager tracks open handles, so if we create a session and try to register a resource we can determine not only if a file is locked, but what processes are using that file.

The Basic steps are reasonably simple, given the complexity of the other alternatives:

  1. Start a Restart Manager Session with rmStartSession
  2. Use rmRegisterResources to attempt to register the file in question.
  3. Use the rmGetList Function to retrieve a list of Processes using said file.
  4. End the Restart Manager Session

The approach is relatively straightforward to create a class to provide this information:

At this point I had a way to retrieve the processes locking a set of files (normally for my uses, one file). leveraging it in the Update Program wouldn’t be entirely straightforward- the intent was to have that information logged, which means it would need to somehow be a part of the Exceptions “ToString()” result. In order to do this I simply created a new Exception:

With the new Exception in place, I was able to use it- My primary interest was in knowing what processes were accessing a file when it was in use. This Exception could be tracked specifically- it would be a Win32Exception with an HRESULT of 0x80004005:

Of course most of that is specific to the Updater implementation; essentially it will track when an updating item encounters an exception and use that to change it’s ListItem’s ProgressBar to be Red, as well as display a cursory set of exception information. The Information is also tracked in the PostGres database in the history, so it can be referred to later.

If the new version works I should be able to determine what other processes were locking the file simply be using the Installation History feature of the Updater. This can help me prove or disprove the possibility of it being Anti-virus related.

Have something to say about this post? Comment!

Tags: , ,