LoadLibrary不重用已加载的库

时间:2014-02-16 15:11:56

标签: c windows dll loadlibrary

我的目录结构如下:

test
  dir
    a.dll  <-- version 1
  a.dll    <-- version 2
  myapp.exe

我希望自己LoadLibrary("dir\\a.dll")将使用版本1而LoadLibrary("a.dll")将使用版本2,而在一起:

LoadLibrary("dir\\a.dll");
LoadLibrary("a.dll");

根据the documentation of LoadLibrary,两者都将引用版本1。

但是,当我尝试在我正在处理的应用程序中执行此操作时,第1行加载版本1,第2行加载版本2.

我试过写一个小的重现器但是在重现器中它按预期工作 - 所以有一些东西在较大的应用程序或加载的dll中打破了。 导致这种情况的原因,以及如何解决?

要强调的是,两个负载在较大的应用程序中是相邻的,在第1行和第2行之间没有系统调用(当然它是相同的过程)。我原本确实想在它们之间放置很多代码,但是看到这个问题并在它们相邻时再现它。

我也试过以下目录结构:

test
  dir
    a.dll  <-- version 1
  myapp.exe
Windows
  System32
    a.dll  <-- version 2

但是,第1行加载版本1,第2行加载版本2.

1 个答案:

答案 0 :(得分:1)

我设法找到了解决方案。实际上,它只需要一些思考 - 回想起来答案是显而易见的:当我的第一个LoadLibrary调用之前已经加载了dll时,就会出现这种情况。所以第一次调用,使用显式路径,加载版本1 - 而第二次调用,没有路径,默认为第一个加载的dll(根据文档),恰好是版本2。

可以通过在第一次LoadLibrary调用之前强行卸载库来解决此问题:

HMODULE alreadyLoaded = GetModuleHandle("a.dll");
if (alreadyLoaded) {
    FreeLibrary(alreadyLoaded);
}

虽然这对我来说已经足够了,但是更完整的解决方案是循环执行,以处理dll之前多次加载的情况:

HMODULE alreadyLoaded = GetModuleHandle("a.dll");
while (alreadyLoaded) {
    FreeLibrary(alreadyLoaded);
    alreadyLoaded = GetModuleHandle("a.dll");
}

当然,这有潜在危险 - 特别是如果原始HMODULE存储在某处,因为这会使其无效。