【问题标题】:Counter argument to overwrite a DLL覆盖 DLL 的反参数
【发布时间】:2019-05-28 13:18:25
【问题描述】:

我们想要热重载一个 DLL。第一个想法是覆盖 .dll 文件,然后从应用程序重新加载它。但是该文件是写保护的。

是否有(记录在案的)反对论点不删除此文件保护并覆盖文件? 如果不存在这样的反论点,我们如何绕过这种保护?

编辑:在 Internet 上找到的参考资料指出 mmap 以及 DLL 可能尚未加载的事实。就我而言,(仅导出的)方法已被调用,因此我可以合理地认为 DLL 已完全加载。

【问题讨论】:

  • "我可以合理地认为 DLL 已完全加载。"但这不是你想要的相反吗?您想重新加载 DLL,但替换文件不会有任何效果,因为它已经完全加载。 (当然,真正的问题是当内存被分页并需要重新分页时。此外,导入的函数现在会指向错误的位置。)
  • 你这样做有点太热了,你必须先使用 FreeLibrary()。由于无论如何您都必须重新绑定导出,所以没有理由让它比这更热。考虑 ReadDirectoryChangesW() 以检测更新被丢弃在指定位置。
  • @Raymond,该 DLL 已经被应用程序使用了一段时间,但是已经编译了一个新版本,应该会替换当前运行的行为。
  • @HansPassant,这实际上是一个很好的答案,只是我的问题有点复杂。 dll 在应用程序运行时由另一个应用程序构建。所以我们还不能释放它。到目前为止,我正在探索的解决方案是先重命名文件(似乎我可以从第三个应用程序执行此操作,而第一个应用程序仍在访问它)。

标签: windows dll


【解决方案1】:

在我们的情况下,我们有一个加载并使用 DLL 的程序。 对这个 DLL 的源代码进行了编辑,我们需要重新编译它并让程序热重载它。问题是 DLL 被锁定以防写入。

我们有另一个程序监视对源文件的任何修改(这实际上是一个自定义脚本编译器)并且需要编译一个 DLL(通过将源脚本翻译成 c++ 代码并调用 clang)。

我们几个月来的解决方案(并且运行良好)是让我们的脚本编译器检查文件是否受到写保护,如果是,则使用临时名称重命名此 dll 并最终编译。

主程序捕捉到这个 dll 的变化并且能够重新加载它。

额外步骤 在编译器启动时,我们检查是否有任何临时 dll 并尝试删除它们。如果删除失败可能是因为 DLL 正在使用中,我们忽略它。

注意:我们需要将 .dll 和 .pdb 移动到一个临时文件中。我们删除 .exp、.ilk 和 .lib 以防万一。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-02
    • 1970-01-01
    • 2020-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-05
    相关资源
    最近更新 更多