通知 Windows Explorer 文件正在使用中






4.84/5 (44投票s)
如何通知 Windows Explorer 应用程序正在使用和锁定哪些文件。
引言
在进行重命名、移动或删除等文件相关操作时,许多人可能会遇到类似这样的消息:
这是 Windows Explorer 通知用户文件正在使用中,因此无法进行任何“更改”(即重命名、移动、删除等)的标准方式。
当然,应用程序也有办法通知 Windows Explorer 哪些文件正在使用。例如,Microsoft Office 应用程序就会这样做。当 Windows Explorer 被通知后,显示文件正在使用的消息看起来会不同:
本文将介绍如何编写一个应用程序来通知 Windows Explorer 文件使用情况。
如何做到?
对于开发者来说,最简单的方法是实现一个名为 IFileIsInUse
的 COM 接口 [^]。不幸的是,此接口仅在 Windows Vista 中可用。幸运的是,还有另一种方法。我将提供一个示例,演示当用户尝试删除正在使用的文件时,Windows Explorer(例如在 Windows XP 中)会做什么。在以下示例中,条目 abc="123"
表示 abc
注册表项的默认值必须等于 123
。
- 首先,Windows Explorer 检查运行对象表 (ROT [^]) 中是否有该文件的条目。用 C# 的术语来说,ROT 可以看作是一种全局可访问的对象,其类型类似于
Dictionary<String, ComObject>
(当然,它不是,因为它不是 .NET 对象)。 - 如果存在该文件的适当条目,它会检查 COM 对象是否实现了
IOleObject
接口。 - 如果实现了该接口,它将调用其
GetUserClassID(ref Guid userClassId)
方法。假设该方法将 GUID{abcdef12-ca3b-a654-e640-bf50b3aba521}
分配给userClassId
参数。 - 然后,它会检查注册表中是否存在以下项(并设置它们的默认值):
HKCR\CLSID\{abcdef12-ca3b-a654-e640-bf50b3aba521}\ProgID="应用程序名称"
HKCR\应用程序名称\CLSID="{abcdef12-ca3b-a654-e640-bf50b3aba521}"
HKCR\应用程序名称\shell\Open\command="应用程序 exe 文件的路径"
- 接下来,为了在消息框中显示应用程序名称,它会读取文件的描述。文件描述可以使用
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();
注册表中的相应项由 FileLocker.Register()
方法创建,由 FileLocker.Unregister()
方法删除。它们需要写入注册表的权限,因此最好在应用程序的安装/卸载过程中调用它们。要成功注册,还需要在程序集中应用 Guid
属性。
FileLocker 类成员
静态方法
void Register()
- 注册FileLocker
。在应用程序的安装过程中调用它。void Unregister()
- 注销FileLocker
。在应用程序的卸载过程中调用它。
构造函数和实例方法
FileLocker(FileInfo fileInfo)
和FileLocker(string path)
- 初始化FileLocker
类的新实例,并通知 Windows Explorer 该文件当前正在被应用程序使用。void Dispose()
- 取消通知并处置对象。
历史
- 1.0 (2008.05.09) - 初始版本。下一版本包含在一个托管在 CodePlex 的新项目中。