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

发布于 2024-07-08 22:50:09 字数 645 浏览 6 评论 0原文

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

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

我该如何解决? 我考虑过编写一个首先启动的帮助应用程序,适当调整环境变量,然后通过 CreateProcess 启动主应用程序。 我确信这会起作用,但它给开发人员带来了困难。 当他们调试主应用程序时,他们不会首先启动辅助应用程序 - 他们甚至不能这样做。

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

我在这里能做什么?

I'm racking my brain trying to come up with an elegant solution to a DLL load problem. I have an application that statically links to other lib files which load DLLs. I'm not loading the DLLs directly. I'd like to have some DLLs in another folder other than the folder that the executable is in. Something like %working_folder%\dlls - I'd rather not have dozens (yes ... dozens) of DLLs in my %working_folder%.

I'm trying to develop something that is part of the main app that will adjust the search path @ startup. The problem I'm running into is that this new custom DLL path isn't in the system search path. When I start the app it crashes (STATUS_DLL_NOT_FOUND) because the necessary DLLs are not in the appropriate places. What I'd like to do is to check @ startup if this new custom DLL folder is in the process environment variable search path and if not add it. Problem is, the application attempts to load all these DLLs before the app executes one line of code.

How do I fix this? I've considered writing a help app that starts first, adjusts the environment variables appropriately and the launches the main app via CreateProcess. This will work I'm sure of it but it makes things difficult on the developers. When they debug the main app they're not going to launch a helper app first - not that they could even do that.

I've tried the registry app path feature with no success. Same chicken and egg problem as before.

What can I do here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

洛阳烟雨空心柳 2024-07-15 22:50:09

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

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

I found Matthew's answer worked for me.

In visual studio 2012 goto your project properties and in
Configuration Properties->Linker->Input->Delay Loaded Dlls
add each dll file that you want to not load until needed.

Although it no longer needs to run before main, this is my code to set the new search path

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.
只有影子陪我不离不弃 2024-07-15 22:50:09

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

我猜测这些库是用 C++ 编写的并且正在加载来自全局范围内某些对象的构造函数的 DLL。 这是有问题的。 请允许我引用 约西·克赖宁

首先在 main() 中执行此操作。 如果您使用 C++,您应该在 main() 之前首先执行此操作,因为人们可以在全局变量的构造函数中使用 FP。 这可以通过以下方式实现:确定特定于编译器的翻译单元初始化顺序、编译您自己的 C/C++ 启动库、使用 LD_PRELOAD 等内容覆盖已编译启动库的入口点、在静态链接程序中覆盖它就在二进制图像中,有一个编码约定,强制在使用 FP 之前调用 FloatingPointSingleton::instance(),或者拍摄那些喜欢在 main() 之前做事的人。 这是一种权衡。

[原始答案如下]

请参阅此页面了解用于加载 DLL 的搜索算法。 您可以使用 SetDllDirectory() 将目录添加到 DLL 搜索路径。

您还应该能够使用 GetEnvironmentVariable()SetEnvironmentVariable()

另一种选择是使用 SetCurrentDirectory()。 如果您使用相对文件名加载任何文件,请确保在加载 DLL 后将工作目录更改回原来的位置。

[Edit - after re-reading the question I see that the problem you're having is that the DLLs are getting loaded before main starts]

I'm guessing that those libraries are written in C++ and are loading the DLLs from the constructor of some objects in global scope. This is problematic. Allow me to quote Yossi Kreinin:

Do it first thing in main(). If you use C++, you should do it first thing before main(), because people can use FP in constructors of global variables. This can be achieved by figuring out the compiler-specific translation unit initialization order, compiling your own C/C++ start-up library, overriding the entry point of a compiled start-up library using stuff like LD_PRELOAD, overwriting it in a statically linked program right there in the binary image, having a coding convention forcing to call FloatingPointSingleton::instance() before using FP, or shooting the people who like to do things before main(). It’s a trade-off.

[Original answer below]

See this page for the search algorithm used for loading DLLs. You can use SetDllDirectory() to add a directory to the DLL search path.

You also should be able to add a directory to the PATH environment variable using GetEnvironmentVariable() and SetEnvironmentVariable().

Another option is to change the current working directory to the folder containing the DLLs with SetCurrentDirectory(). Just make sure to change the working directory back after loading the DLLs if you ever load any files using relative filenames.

一城柳絮吹成雪 2024-07-15 22:50:09

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

My recommendation is to use delayload linking for the DLLs and call SetDllDirectory() early enough so it can find them when the methods/functions are invoked.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文