在应用程序启动时添加自定义DLL搜索路径

在应用程序启动时添加自定义DLL搜索路径,dll,path,setdlldirectory,Dll,Path,Setdlldirectory,我绞尽脑汁想找出一个优雅的解决DLL加载问题的方法。我有一个静态链接到其他加载DLL的lib文件的应用程序。我不是直接加载DLL。我希望在可执行文件所在的文件夹之外的其他文件夹中有一些DLL。类似于%working\u folder%\dll的内容-我不希望在我的%working\u folder%中有几十个(是的…几十个)DLL 我正在尝试开发一些东西,这是主应用程序的一部分,可以调整@startup的搜索路径。我遇到的问题是,这个新的自定义DLL路径不在系统搜索路径中。当我启动应用程序时,它

我绞尽脑汁想找出一个优雅的解决DLL加载问题的方法。我有一个静态链接到其他加载DLL的lib文件的应用程序。我不是直接加载DLL。我希望在可执行文件所在的文件夹之外的其他文件夹中有一些DLL。类似于%working\u folder%\dll的内容-我不希望在我的%working\u folder%中有几十个(是的…几十个)DLL

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

我该如何解决这个问题?我考虑编写一个帮助应用程序,首先启动,适当调整环境变量,然后通过CreateProcess启动主应用程序。这将工作,我相信它,但它使事情对开发人员困难。当他们调试主应用程序时,他们不会首先启动助手应用程序——他们甚至不能这样做

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


我能在这里做什么?

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

我猜想这些库是用C++编写的,并且正在从全局范围内的一些对象的构造函数中加载DLL。这是有问题的。请允许我引述:

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

[以下原始答复]

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

您还应该能够使用和将目录添加到PATH环境变量


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

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

我发现Matthew的答案对我来说很有用

在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.

注意:在DllMain中有很多事情是不能做的,比如加载注册表值。但是调用SetDllDirectory(“./dll\u dir”)可能有效。未测试。Windows在OS X中是否具有类似@load\u路径的功能?即相对于当前DLL或其他内容定义的搜索路径?非常感谢。