在应用程序启动时添加自定义DLL搜索路径
我绞尽脑汁想找出一个优雅的解决DLL加载问题的方法。我有一个静态链接到其他加载DLL的lib文件的应用程序。我不是直接加载DLL。我希望在可执行文件所在的文件夹之外的其他文件夹中有一些DLL。类似于%working\u folder%\dll的内容-我不希望在我的%working\u folder%中有几十个(是的…几十个)DLL 我正在尝试开发一些东西,这是主应用程序的一部分,可以调整@startup的搜索路径。我遇到的问题是,这个新的自定义DLL路径不在系统搜索路径中。当我启动应用程序时,它会崩溃(状态为未找到DLL),因为必要的DLL不在适当的位置。我想做的是检查@startup这个新的自定义DLL文件夹是否在进程环境变量搜索路径中,如果没有,则添加它。问题是,应用程序试图在执行一行代码之前加载所有这些DLL 我该如何解决这个问题?我考虑编写一个帮助应用程序,首先启动,适当调整环境变量,然后通过CreateProcess启动主应用程序。这将工作,我相信它,但它使事情对开发人员困难。当他们调试主应用程序时,他们不会首先启动助手应用程序——他们甚至不能这样做 我尝试了注册表应用程序路径功能,但没有成功。和以前一样的鸡和蛋问题在应用程序启动时添加自定义DLL搜索路径,dll,path,setdlldirectory,Dll,Path,Setdlldirectory,我绞尽脑汁想找出一个优雅的解决DLL加载问题的方法。我有一个静态链接到其他加载DLL的lib文件的应用程序。我不是直接加载DLL。我希望在可执行文件所在的文件夹之外的其他文件夹中有一些DLL。类似于%working\u folder%\dll的内容-我不希望在我的%working\u folder%中有几十个(是的…几十个)DLL 我正在尝试开发一些东西,这是主应用程序的一部分,可以调整@startup的搜索路径。我遇到的问题是,这个新的自定义DLL路径不在系统搜索路径中。当我启动应用程序时,它
我能在这里做什么?[编辑-重新阅读问题后,我发现您遇到的问题是在
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或其他内容定义的搜索路径?非常感谢。