【问题标题】:How to unload C++ Shell Extension DLL properly如何正确卸载 C++ Shell 扩展 DLL
【发布时间】:2012-07-06 16:13:24
【问题描述】:

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

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

它工作正常。但问题是:

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

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

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

【问题讨论】:

  • 认为杀死explorer.exe 会有所帮助的想法是错误的。首先,这是一件非常具有侵略性的事情(Windows Installer 会将正在使用的文件 移动 到同一卷上的另一个位置以将新文件安装到原始位置),其次它可能不会完全可以工作,因为用户可能使用的是完全不同的文件管理器,它使用了 shell 扩展。我自己这样做,而做出这些假设的安装人员只是烦人。你可以远程关闭引用,造成各种破坏。不要这样做!
  • 我和@0xC0000022L 在一起。我和其他人一样讨厌重新启动,但我认为这需要一个。在资源管理器启动之前,您可以在系统再次启动时完成安装。
  • @eran:实际上只需要重启受影响的应用程序(或注销)。
  • 您的外壳扩展 DLL 通过外壳对话框加载到其他进程中。就像在记事本中的文件 + 打开一样。您可以重命名原始 DLL 并将新的 DLL 安装到位,但需要注销才能使其生效。
  • @HansPassant:只是想知道,你知道这个问题的最终答案吗:新的应用程序实例会立即使用新的 shell 扩展吗?我不是 100% 确定。

标签: visual-studio-2010 winapi visual-c++ shell-extensions


【解决方案1】:

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

大多数人似乎还没有意识到MoveFile(和MoveFileEx)可用于移动当前正在使用的 DLL 或 EXE 文件应用。

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

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

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

【讨论】:

  • 我们正在使用 bitrock 安装程序。我会试试你的建议。
  • 如果存在 DLL 锁,Bitrock 安装程序会复制附加一些唯一编号的新文件。但用户必须重新启动系统。在重新启动期间,它将删除旧的 dll 并从 dll 中删除唯一编号。
  • @JChan:听起来他们正在使用 Windows Installer 正在使用的技术以及我所描述的技术。
  • 解决方案并非万无一失,即在升级过程中,我们会取消注册旧的dll,复制新的dll并注册。如果发生 dll 锁定,它将永远不会注册新的 dll。但它会用新的dll替换旧的dll。这是一个问题。需要注册新的dll。我想知道如何解决这个问题
  • @JChan:如果你的意思是自我注册,你应该完全停止这样做。 MS 建议不要将其用于自己的技术(Windows Installer)是有原因的。而是自己设置注册表值。此外,在升级期间很少需要注册和注销,因为大部分值可能在两个版本的 DLL 之间共享。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2019-10-12
    • 1970-01-01
    • 2016-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    • 1970-01-01
    • 2014-05-14
    相关资源
    最近更新 更多