2011-01-19 201 views
2

我有以下情况,不能拿出任何好的解决方案。DLL依赖项问题/ SetDLLDirectory

我在C:\ ProgFiles \ MyApp中安装了一个C++应用程序(app.exe)。它需要一堆DLL,我安装在C:\ ProgFiles \ MyApp \ bin中。我想把它们放在一个子文件夹中,因为它们有很多。

现在,当我启动app.exe时,需要让Windows知道所需的DLL在哪里。在过去,我为此使用了PATH环境变量,但是我不能再这样做了,因为我将使用单独的安装程序创建另一个应用程序,该安装程序使用许多具有相同名称的DLL。

我想在应用程序的开头调用SetDLLDirectory - 但我忘了,因为所需的DLL丢失,它在到达那里失败。

有什么建议吗?

回答

4

请参阅微软的this article,其中讨论了DLL搜索路径和相关问题。

尤其要注意的是,如果您没有将它们放在您应用程序的目录中,则当前目录优先,这是一个安全漏洞。

一种解决方案是使用LoadLibrary(具有完全合格的路径),然后使用GetProcAddress。那会很痛苦。

没有正常的用户会去C:\Program Files\YourApp周围挖掘,这是你应该把它们放在哪里,除非你有充分的理由不要。

2

我认为你最好将.DLL文件放在与.EXE相同的目录中 - 可能会有很多,但是这个工作并且没有人会在那个目录中看到,所以我不担心太多了。

如果你依赖PATH,那么你总是会受到用户的摆布,导致你额外的支持开销,因为没有任何理由。

4

delay load选项与SetDLLDirectory结合使用可能会起作用。系统在第一次引用时动态加载延迟加载的DLL。如果使用Visual Studio,则可以指定在链接器输入选项下的项目属性中延迟加载哪些DLL。有一个Delay Loaded DLLs字段用于指定它们。否则,您可以在链接器命令中指定/DELAYLOAD:mydll.dll

+0

我在这里的问题是,我将不得不延迟加载的DLL很多,当我们整合新的第三方模块列表经常改变。此外,如果所需的DLL不存在,我希望应用程序只启动失败,以便我可以修复它(而不是仅在实际尝试使用该DLL时发现该问题)。 – Warpin 2011-01-19 21:28:10

0

解决问题的一种方法是使用SetDllDirectory函数;但是,它需要你在程序上执行的第一件事(这很难做到),我的解决方案是使用第三方程序来设置dll目录,然后调用你的EXE文件作为一个新进程:

这是第三方这将是一个EXE文件:

#include <windows.h> 

SetDllDirectory(_T(".dll location")); 

STARTUPINFOW siStartupInfo; 
PROCESS_INFORMATION piProcessInfo; 
memset(&siStartupInfo, 0, sizeof(siStartupInfo)); 
memset(&piProcessInfo, 0, sizeof(piProcessInfo)); 
siStartupInfo.cb = sizeof(siStartupInfo); 

if (CreateProcessW(L".exe location",NULL, NULL, NULL, FALSE, 
    0, NULL, NULL, 
    &siStartupInfo, &piProcessInfo)) 
{ 
    /* This line waits for the process to finish. */ 
    /* You can omit it to keep going whilst the other process runs */ 
    //dwExitCode = WaitForSingleObject(piProcessInfo.hProcess, (SecondsToWait * 1000)); 
} 
else 
{ 
    /* CreateProcess failed */ 
    //iReturnVal = GetLastError(); 
} 
return 0;