在进行文件操作,如重命名、移动或删除时,可能会遇到Windows Explorer提示某些文件正在使用中,因此无法进行更改。实际上,应用程序可以通过特定的方式通知Windows Explorer哪些文件正在使用中,例如Microsoft Office应用程序就是这样做的。当Windows Explorer收到通知时,显示的文件正在使用的消息会有所不同。本文将解释如何编写一个应用程序来通知Windows Explorer哪些文件正在使用中。
对于开发者来说,最简单的方法是实现一个名为IFileIsInUse
的COM接口。不幸的是,这个接口只在Windows Vista中可用。幸运的是,还有另一种方法。以下示例展示了当用户尝试删除一个正在使用的文件时,Windows Explorer(例如,在Windows XP中)的行为。
首先,Windows Explorer会检查运行对象表(ROT)中是否有文件的条目。如果存在适当的条目,它会检查COM对象是否实现了IOleObject
接口。如果实现了该接口,它会调用其GetUserClassID(ref Guid userClassId)
方法。假设该方法将{abcdef12-ca3b-a654-e640-bf50b3aba521}
GUID分配给userClassId
参数。
然后,它会检查注册表中是否存在以下键(及其默认值设置):
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"
为了在消息框中显示应用程序名称,它会读取文件的描述。文件描述可以通过AssemblyTitle
属性设置。如果一切正常,Windows Explorer会显示一个消息框,显示应用程序的名称。
创建了一个名为FileLocker
的类,它提供了通知Windows Explorer当前应用程序使用的文件的方法。该类实现了IDisposable
接口,因此可以使用using
关键字方便地使用。以下代码展示了示例用法:
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();
void Register()
- 注册FileLocker
。在应用程序的安装过程中调用它。void Unregister()
- 注销FileLocker
。在应用程序的卸载过程中调用它。FileLocker(FileInfo fileInfo)
和FileLocker(string path)
- 初始化FileLocker
类的新实例,并通知Windows Explorer指定的文件当前正在被应用程序使用。void Dispose()
- 取消通知并释放对象。