Click here to Skip to main content
Click here to Skip to main content

Notifying Windows Explorer about files in use

By , 26 Mar 2013
 

Introduction

While doing some file-related operations like renaming, moving, or deleting, many of you might encounter this kind of a message:

Error - file is in use

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 a 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:

fileisinuse/error2.png

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.

  1. 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).
  2. If there is an appropriate entry for the file, it checks if the COM object implements the IOleObject interface.
  3. 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.
  4. 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"
  5. Next, in order to display the 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 is 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 the 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:

// GUID, which must be unique, used to register an application in the registry
[assembly: Guid("{abcdef12-ca3b-a654-e640-bf50b3aba521}")]
// Application title which will be shown by the Windows Explorer
[assembly: AssemblyTitle("FileLockerApplication")]

...

// registers the application in the registry
FileLocker.Register();

string path = "some_file.txt";
// creates or opens the file and locks it
using (FileStream fs = File.Open(path, FileMode.OpenOrCreate,
                                 FileAccess.ReadWrite, FileShare.None))
// notifies Windows Explorer that the file is in use
using (FileLocker fl = new FileLocker(path))
{
    // here might be some code
}
// deletes the file
File.Delete(path);

// unregisters the application from the registry
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 the 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. Invokes it from the application during the installation process.
  • void Unregister() - Unregisters the FileLocker. Invokes it from the application during the uninstallation process.

Constructors and instance methods

  • FileLocker(FileInfo fileInfo) and 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. The next version is included in a new project hosted at CodePlex.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)

About the Author

Lukasz Swiatkowski
Software Developer
Poland Poland
Member
I am a graduate of Wroclaw University of Technology, Poland.
 
My interests: reading, programming, drawing, Japan, yoga, tai-chi.
 
My website: www.lukesw.net

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionWorking on shared foldersmemberpetr.snobelt2 Apr '13 - 0:34 
Hello, thank you for nice class, but it looks like it work only for user which run your application.
 
If it lock file on shared drive, are other users informed about lock? Is something like this possible?
 
Thank you
GeneralMy vote of 5memberMember 43208441 Apr '13 - 15:40 
Nice Work , But I couldnt Find
any Download on CodePlex Link you provided ! ?
Thanks
GeneralKeep the lockingmemberXmen W.K.10 Jun '10 - 16:10 
This is exactly what I needed for securing some files. But the thing is that the security can be break easily, so I want to keep the lock even application is closed.
 
eg.
Application runs, creates and locks some files so that nobody else can use it. And on form closing, unlocks those files and delete 'em as well. But this can be break easily by killing the process using Task Manager. So I'm thinking, is it possible to keep the lock if application get killed by any other process ?


TVMU^P[[IGIOQHG^JSH`A#@`RFJ\c^JPL>;"[,*/|+&WLEZGc`AFXc!L
%^]*IRXD#@GKCQ`R\^SF_WcHbORY87֦ʻ6ϣN8ȤBcRAV\Z^&SU~%CSWQ@#2
W_AD`EPABIKRDFVS)EVLQK)JKQUFK[M`UKs*$GwU#QDXBER@CBN%
R0~53%eYrd8mt^7Z6]iTF+(EWfJ9zaK-i’TV.C\y<pŠjxsg-b$f4ia>
-----------------------------------------------
128 bit encrypted signature, crack if you can

GeneralMean CodememberJonathan C Dickinson14 May '08 - 0:14 
that is some wicked code man.
GeneralRe: Mean CodemvpLukasz Swiatkowski17 May '08 - 5:51 
Next version will be even more wicked Wink | ;)
 
~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralRe: Mean CodememberJonathan C Dickinson18 May '08 - 5:06 
An interesting method would be to wrap the System.Steam class. For example;
 
Stream() //Ctor
{
FileInUse.Notify(Assembly.GetEntryAssembly().Location);
}
 
~Stream() //Dtor
{
FileInUse.Denotify(Assembly.GetEntryAssembly().Location);
}
GeneralRe: Mean CodemvpLukasz Swiatkowski18 May '08 - 5:12 
That's a great idea. In this way it would work like other decorators from System.IO namespace.
 
Lukasz
 
~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralGood Jobmemberklaus_b13 May '08 - 19:33 
A really good and helpfull article. You've shown me another point of view to one of my old problems.
GeneralRe: Good JobmvpLukasz Swiatkowski17 May '08 - 5:49 
Thanks. I'm glad you like it Smile | :)
 
~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralRe: Good Jobmemberpwasser18 Sep '08 - 19:38 
And me
 
Peter Wasser

GeneralNice manmvpSacha Barber9 May '08 - 2:59 
Hey, how did you learn all the P/Invoke stuff, are you more into C++/Win32 or does it come natural.
 
PS : This is way better than the button Smile | :)
 
Sacha Barber
  • Microsoft Visual C# MVP 2008
  • Codeproject MVP 2008
Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

GeneralRe: Nice manmvpLukasz Swiatkowski9 May '08 - 7:17 
Before I started programming in C#/VB.NET, I used to develop in Visual C++. I am familiar with both Win32 and COM, so it is very helpful when I must use P/Invoke.
 
PS. Thanks Smile | :)
 
~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralRe: Nice manmvpSacha Barber10 May '08 - 4:43 
Lukasz Swiatkowski wrote:
I am familiar with both Win32 and COM

 
Nice.
 
I know nothing about Win32, and only some COM stuff. Good stuff to know, to get to know this sort of thing what would you suggest, just learn C++, or is there another route, learning .NET keeps me busy enough, .NET 3.0/3.5 are BIG subjects, and I feel I have only just really got WPF, next is WF for me.
 
Argghh no time, good article though man, I cant fault your stuff when you do things like this.
 
How do you find the names of the P/Invoke stuff you need, is is guess work, or do you just know that you had to use User.dll, I'm curious about this...I just dont know P/Invoke so when I see people do stuff like this, I am always curious how they knew that particular method would do this or that.
 
Sacha Barber
  • Microsoft Visual C# MVP 2008
  • Codeproject MVP 2008
Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

GeneralRe: Nice manmvpLukasz Swiatkowski11 May '08 - 11:55 
I think that learning C++ is not required to have good knowledge about WinAPI/COM, but creating just a few simple C++ applications from scratch using WinAPI (and maybe a little bit of COM) would be a great experience.
 
I don't like to guess. If I have to use some WinAPI/COM which I don't know yet, I prefer searching MSDN Library.
 
Regards,
Lukasz
 
~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralRe: Nice manmvpSacha Barber11 May '08 - 21:07 
Lukasz
 
Good advice here, I may just do that one day...The point was that how do you know what function to look for in MSDN, the Win32 stuff has function names that dont seem to tie up with what the method actual does...It really is a black art
 
Sacha Barber
  • Microsoft Visual C# MVP 2008
  • Codeproject MVP 2008
Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

GeneralRe: Nice manmvpLukasz Swiatkowski12 May '08 - 8:37 
Well... I know many of WinAPI functions and COM interfaces, but when I don't know what to use, I'm searching for samples/tutorials in which I can find those functions/interfaces.
 
Lukasz
 
~~~~~~~~~~~~~~~~~~~
My website: www.lukesw.net

GeneralRe: Nice manmvpSacha Barber12 May '08 - 22:17 
But how do you know what function/interface to look for, the names are so strange?
 
Anyway good stuff, from you. Apart from the button I have loved all your other articles, they are CLEVER
 
Sacha Barber
  • Microsoft Visual C# MVP 2008
  • Codeproject MVP 2008
Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

GeneralRe: Nice manmemberTheo Bebekis12 May '10 - 4:43 
Regarding Win32 API programming and plain good old C language, there is a "Holly Bible": it is the book Programming Windows by Charles Petzold (the herow). It was and still is the Holly Bible (from the Windows 3 era to present time). Although it covers just the basic APIs (user32, gdi32 and kernel32) and that not so exhaustivelly.
 
Another good choice, in Delphi language, consists of two books: The Tomes of Delphi 3, Win32 Core API and The Tomes of Delphi 3, Win32 Graphics API. Those two books cover more APIs than Petzold but with a different style.
 
Regarding COM (oh my), well it depends. You may start searching for the right interfaces, using the OLE/COM Object Viewer from the Microsoft Windows SDK. And then there is always the MSDN, the Win32 and COM Development section.
 
(There is legendary book though, "Inside Ole 2", but...)
 
Programming COM with C++ is just a pain. C# makes it easy enough, except of late binding (i.e. Variants and dispinterfaces). And Delphi for Win32 was the best tool I ever used in the area of COM programming.
 
HTH
--------------------
Theo Bebekis
Thessaloniki, Greece

GeneralRe: Nice manmvpSacha Barber12 May '10 - 6:02 
Thanks for that man, I actually bought the Petzold one some time back, Ill read it one day. So much to learn with c#/.net, arggghhhh
Sacha Barber
  • Microsoft Visual C# MVP 2008-2010
  • Codeproject MVP 2008-2010
Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

GeneralRe: Nice manmemberTheo Bebekis12 May '10 - 6:59 
For anyone who wants to study the code of a full blown application written the old hard way, i.e. using just plain C and the Win32 API, handling windows messages, dialog resources, etc. there is the WiZ, the Win32 GUI front end for the excellent Zip and UnZip dlls of the InfoZip team. Their site is at http://www.info-zip.org/[^] (thanks forever guys).
 
WiZ sources can be found at http://sourceforge.net/projects/infozip/files/WiZ[^]
 
Just get the file with the .zip extension.
--------------------
Theo Bebekis
Thessaloniki, Greece

GeneralRe: Nice manmvpSacha Barber12 May '10 - 7:04 
Cool thanks man.
Sacha Barber
  • Microsoft Visual C# MVP 2008-2010
  • Codeproject MVP 2008-2010
Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue
 
My Blog : sachabarber.net

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 27 Mar 2013
Article Copyright 2008 by Lukasz Swiatkowski
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid