7

我有用C++ 和 COM 编写的shell 扩展 dll该 dll 已注册并加载到内存中。我的升级设置程序将执行以下操作:

  • 注销shell扩展dll,杀死explorer.exe
  • 复制更高版本的shell扩展dll(步骤2)
  • 启动 explorer.exe

它工作正常。但问题是:

如果用户打开了任何其他应用程序(Internet Explorer,有时是 Windows 任务管理器,记事本等),则步骤 2将失败。

升级 dll 时有什么方法可以关闭所有 shell 扩展 dll 挂钩。

在 dll 中,我使用 GetOverlayInfo、上下文菜单、数据库连接等

4

2 回答 2

8

简单地说:不要这样做(即不要强行卸载它)。您必须枚举所有加载了您的 shell 扩展的进程,然后“重新启动”这些进程。这是非常具有侵略性的,坦率地说:不良行为(对于安装程序)。这也需要您的安装程序可能不需要的特殊权限。

大多数人似乎仍然不知道的是MoveFile(and MoveFileEx) 可用于移动正在运行的应用程序当前正在使用的 DLL 或 EXE 文件。

这是 Windows Installer 采用的方法。安装后,您有没有注意到\Config.msi给定驱动器根目录中的文件夹.msi?该文件夹实际上包含(已移动并通常重命名为某个唯一的“临时”名称)已被移出但当时仍在使用的原始文件。然后通常安排在启动时删除它们(MoveFileExwith MOVEFILE_DELAY_UNTIL_REBOOT)。

您可以在自制安装程序中使用相同的机制,将正在使用的旧文件移出其原始位置,并立即将另一个移入。然后,任何新的应用程序实例都将使用新的 shell 扩展 (*),而旧的应用程序将继续被任何在某个时间点加载它的正在运行的应用程序使用。

(*) 我不能 100% 确定这一点,因为适用于 DLL 加载并防止在某些情况下再次加载同名模块的规则。

于 2012-07-06T16:39:02.883 回答
1

根据您的安装程序,您可能能够使用 Windows Vista+ 中的重新启动管理器支持。这将允许您的设置查询正在使用您的 DLL 的每个应用程序,并尝试优雅地关闭它们。如果它们不能,那么您将需要在重新启动时注册它以进行更换。设置完成后,重新启动管理器将尝试重新启动它关闭的所有程序(支持重新启动)。

于 2013-03-13T09:25:06.880 回答