Download source code, compiled library and samples — 12.4 KB
View the original version of the article at The Code Project
Introduction
While doing some files-related operations like renaming, moving or deleting, many of you might encounter this kind of message:

This is the standard way Windows Explorer notifies the user that some file is in use, and therefore it cannot be “changed” in any way (that is renamed, moved, deleted, etc.)
Of course there is the way for an application to notify Windows Explorer about which files are in use. For example Microsoft Office applications do that. When Windows Explorer is notified, the message saying that the file is in use looks different:

This article explains how to write an application which notifies Windows Explorer about used files.
How to do it?
The easiest way for a developer is to implement a COM interface named IFileIsInUse
[^]. Unfortunately, this interface is available only in Windows Vista. Luckily, there is another way. I show an example demonstrating what Windows Explorer (e.g. in Windows XP) does when the user tries to delete a file which is in use. In the following example an entry abc=“123”
will mean that the default value of the abc
registry key has to be equal to 123
.
- At first, the Windows Explorer checks if there is an entry for the file in the Running Object Table (ROT[^]). Using C# terminology one could say that the ROT is a kind of globally accessible object whose type would be
Dictionary<String, ComObject>
(of course it is not, because it is not a .NET object).
- If there is an appropriate entry for the file, it checks if the COM object implements the
IOleObject
interface.
- If the interface is implemented, it invokes its
GetUserClassID(ref Guid userClassId)
method. Let’s assume that the method assigns a {abcdef12-ca3b-a654-e640-bf50b3aba521}
GUID to the userClassId
parameter.
- Then it checks if the following keys are in the registry (with their default values set):
HKCR\CLSID\{abcdef12-ca3b-a654-e640-bf50b3aba521}\ProgID=“ApplicationName”
HKCR\ApplicationName\CLSID=“{abcdef12-ca3b-a654-e640-bf50b3aba521}”
HKCR\ApplicationName\shell\Open\command=“path to the application exe file”
- Next, in order to display application name in the message box, it reads the description of the file. The file description can be set using the
AssemblyTitle
attribute.
If everything was OK, Windows Explorer shows a message box (like the second one from this article) with the name of the application.
Using the code
I have created a FileLocker
class which provides methods to notify Windows Explorer, which files are currently used by the application. The class implements the IDisposable
interface, so it can be comfortably used with the using
keyword. The sample usage is shown on the following code:
[assembly: Guid("{abcdef12-ca3b-a654-e640-bf50b3aba521}")]
[assembly: AssemblyTitle("FileLockerApplication")]
...
FileLocker.Register();
string path = "some_file.txt";
using (FileStream fs = File.Open(path, FileMode.OpenOrCreate,
FileAccess.ReadWrite, FileShare.None))
using (FileLocker fl = new FileLocker(path))
{
}
File.Delete(path);
FileLocker.Unregister();
The appropriate keys in the registry are created by the FileLocker.Register()
method, and deleted by the FileLocker.Unregister()
method. They require a permission to write to the registry, so it is best to invoke them from the application during installation/uininstallation process. To successfully register there is also needed a Guid
attribute applied to the assembly.
FileLocker class members
Static methods
void Register()
— Registers the FileLocker. Invoke it from the application during the installation process.
void Unregister()
— Unregisters the FileLocker. Invoke it from the application during the uninstallation process.
Constructors and instance methods
FileLocker(FileInfo fileInfo)
& FileLocker(string path)
— Initializes a new instance of the FileLocker
class and notifies Windows Explorer that the specified file is currently used by the application.
void Dispose()
— Cancels the notification and disposes the object.
History
- 1.0 (09.05.2008) — first version.
License
This article, along with any associated source code and files, is licensed under The Common Public License Version 1.0 (CPL).