添加自定义DLL搜索路径@ application startup

时间:2008-11-29 03:04:49

标签: dll path setdlldirectory

我正在绞尽脑汁试图想出一个解决DLL加载问题的优雅解决方案。我有一个静态链接到其他加载DLL的lib文件的应用程序。我没有直接加载DLL。我想在可执行文件所在的文件夹之外的另一个文件夹中安装一些DLL。像%working_folder%\ dlls这样的东西 - 我宁愿在我的%working_folder%中没有几十个(是...几十个)DLL 。

我正在尝试开发一些主要应用程序的一部分,它将调整@ startup的搜索路径。我遇到的问题是这个新的自定义DLL路径不在系统搜索路径中。当我启动应用程序时它崩溃(STATUS_DLL_NOT_FOUND)因为必要的DLL不在适当的位置。我想做的是检查@ startup是否这个新的自定义DLL文件夹在进程环境变量搜索路径中,如果没有添加它。问题是,应用程序尝试在应用程序执行一行代码之前加载所有这些DLL。

我该如何解决这个问题?我考虑过编写一个首先启动的帮助应用程序,适当调整环境变量,然后通过CreateProcess启动主应用程序。这将有效我确信它,但它使开发人员的事情变得困难。当他们调试主应用程序时,他们不会首先启动帮助应用程序 - 而不是他们甚至可以这样做。

我尝试过注册表应用程序路径功能但没有成功。像以前一样鸡和鸡蛋问题。

我可以在这做什么?

3 个答案:

答案 0 :(得分:3)

我发现马修的答案对我有用。

在visual studio 2012中转到您的项目属性并进入 配置属性 - >链接器 - >输入 - >延迟加载的Dll 添加您想要在需要之前不加载的每个dll文件。

虽然它不再需要在main之前运行,但这是我设置新搜索路径的代码

class RunBeforeMain
{
public:
    RunBeforeMain()
    {
        const TCHAR* dllPathEnvName= name of env variable to directory containing dlls
        const TCHAR* pathEnvName= TEXT("Path");


        TCHAR newSearchPath[4096];
        ::GetEnvironmentVariable(dllPathEnvName, newSearchPath, MAX_PATH);

             //append bin
        _tcscat_s(newSearchPath, MAX_PATH, TEXT("bin;"));
        size_t length = _tcslen(newSearchPath);

            //append existing Path
        ::GetEnvironmentVariable(pathEnvName, newSearchPath + length, 4096-length);
        ::SetEnvironmentVariable(pathEnvName, newSearchPath);

    }
};
static RunBeforeMain runBeforeMain; //constructor code will run before main.

答案 1 :(得分:2)

[编辑 - 重新阅读问题后,我发现您遇到的问题是DLL在main开始之前加载了

我猜这些库是用C ++编写的,并且是从全局范围内某些对象的构造函数加载DLL的。这是有问题的。请允许我引用Yossi Kreinin

  

在main()中做第一件事。如果你使用C ++,你应该在main()之前做第一件事,因为人们可以在全局变量的构造函数中使用FP。这可以通过找出编译器特定的转换单元初始化顺序,编译自己的C / C ++启动库,使用LD_PRELOAD之类的东西覆盖已编译的启动库的入口点,在静态链接的程序中覆盖它来实现。在二进制图像中,具有强制在使用FP之前调用FloatingPointSingleton :: instance()的编码约定,或者在main()之前拍摄喜欢做事的人。这是一种权衡。

[下面的原始答案]

有关用于加载DLL的搜索算法,请参阅this page。您可以使用SetDllDirectory()将目录添加到DLL搜索路径。

您还应该能够使用GetEnvironmentVariable()SetEnvironmentVariable()将目录添加到PATH环境变量中。

另一个选项是将当前工作目录更改为包含SetCurrentDirectory()的DLL的文件夹。如果您使用相对文件名加载任何文件,请确保在加载DLL后更改工作目录。

答案 2 :(得分:2)

我的建议是使用DLL的延迟加载链接并尽早调用SetDllDirectory(),以便在调用方法/函数时找到它们。