65.9K
CodeProject 正在变化。 阅读更多。
Home

通知 Windows Explorer 文件正在使用中

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.84/5 (44投票s)

2008年5月8日

LGPL3

3分钟阅读

viewsIcon

89061

downloadIcon

652

如何通知 Windows Explorer 应用程序正在使用和锁定哪些文件。

引言

在进行重命名、移动或删除等文件相关操作时,许多人可能会遇到类似这样的消息:

Error - file is in use

这是 Windows Explorer 通知用户文件正在使用中,因此无法进行任何“更改”(即重命名、移动、删除等)的标准方式。

当然,应用程序也有办法通知 Windows Explorer 哪些文件正在使用。例如,Microsoft Office 应用程序就会这样做。当 Windows Explorer 被通知后,显示文件正在使用的消息看起来会不同:

fileisinuse/error2.png

本文将介绍如何编写一个应用程序来通知 Windows Explorer 文件使用情况。

如何做到?

对于开发者来说,最简单的方法是实现一个名为 IFileIsInUse 的 COM 接口 [^]。不幸的是,此接口仅在 Windows Vista 中可用。幸运的是,还有另一种方法。我将提供一个示例,演示当用户尝试删除正在使用的文件时,Windows Explorer(例如在 Windows XP 中)会做什么。在以下示例中,条目 abc="123" 表示 abc 注册表项的默认值必须等于 123

  1. 首先,Windows Explorer 检查运行对象表 (ROT [^]) 中是否有该文件的条目。用 C# 的术语来说,ROT 可以看作是一种全局可访问的对象,其类型类似于 Dictionary<String, ComObject>(当然,它不是,因为它不是 .NET 对象)。
  2. 如果存在该文件的适当条目,它会检查 COM 对象是否实现了 IOleObject 接口。
  3. 如果实现了该接口,它将调用其 GetUserClassID(ref Guid userClassId) 方法。假设该方法将 GUID {abcdef12-ca3b-a654-e640-bf50b3aba521} 分配给 userClassId 参数。
  4. 然后,它会检查注册表中是否存在以下项(并设置它们的默认值):
    • HKCR\CLSID\{abcdef12-ca3b-a654-e640-bf50b3aba521}\ProgID="应用程序名称"
    • HKCR\应用程序名称\CLSID="{abcdef12-ca3b-a654-e640-bf50b3aba521}"
    • HKCR\应用程序名称\shell\Open\command="应用程序 exe 文件的路径"
  5. 接下来,为了在消息框中显示应用程序名称,它会读取文件的描述。文件描述可以使用 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 的新项目中。
© . All rights reserved.