强制 Qt5 从 exe 目录加载 SSL dll
Posted
技术标签:
【中文标题】强制 Qt5 从 exe 目录加载 SSL dll【英文标题】:Force Qt5 to load SSL dlls from exe dir 【发布时间】:2015-06-03 13:30:09 【问题描述】:更新对不起,伙计们,我错误地确定了问题。一切正常,错误出现在“其他程序逻辑”中。请删除或关闭问题。
Qt5 设计为在程序启动时在 main()
中的任何指令之前加载 libeay32.dll
和 ssleay32.dll
(因为它是静态的)。
(详情:位于qtbase\src\network\ssl\qsslsocket_openssl_symbols.cpp
:
static QPair<QSystemLibrary*, QSystemLibrary*> loadOpenSslWin32()
)
问题:
我的程序不是以 exe 目录作为工作目录开始的libeay32.dll
和 ssleay32.dll
位于其 exe 目录中
用户无法在系统目录中安装 OpenSSL
用户无法更改 PATH 变量
我无法重新编译 Qt,即使用 openssl-linked 编译的静态 Qt 发布程序
Qt 按此顺序加载搜索 dll(来自qtbase\src\corelib\plugin\qsystemlibrary.cpp
):
-
应用路径。
系统库路径。
尝试 PATH 环境变量中的所有路径。
没有。 1是应用程序路径,但实际上并没有在那里搜索。
我的程序:
int main()
// at this point Qt5 already checked and tried to load the DLLs
// so this:
ChangeCurrentWorkingDirectoryToExeDir(); // some function to change cwd to current exe dir
// does not work :-(
// ... other program logic ..
更改工作目录后如何强制 Qt5 重新加载 OpenSSL DLL? 可能有人已经遇到过这个问题...
更新对不起,伙计们,我错误地确定了问题。一切正常,错误出现在“其他程序逻辑”中。请删除或关闭问题。
【问题讨论】:
为什么不从 exe 目录作为工作目录启动应用程序? @m.s.它作为 URI 协议处理程序 (msdn.microsoft.com/en-us/en_us/library/aa767914(VS.85).aspx) 启动,无法指定工作目录 好的,但是你为什么不能重新编译Qt呢?为什么 PATH 变量是不可修改的? 这个函数是静态的,但这并不意味着它正在执行那个函数,这仍然需要你自己做。 如果 Qt 会从工作目录加载库,那将是一个安全问题(可能会注入其他 DLL)。我不明白为什么可执行文件的目录不应该工作,这是放置文件的通常位置。 【参考方案1】:QSystemLibrary::load
与 onlySystemDirectory = false
一起调用 SSL,因此 QFileInfo(qAppFileName()).path()
是搜索 DLL 的第一个位置。搜索顺序:
-
应用程序目录
系统路径(例如 C:\Windows\System32)
PATH 中的所有路径
我没有找到这方面的文档,但在我们的软件中,当 SSL libeay32.dll
和 ssleay32.dll
与应用程序 .exe 位于同一目录中时,Qt 会发现它们
如果您有qt.conf
,则可能会应用默认库值,即.\lib
。
【讨论】:
感谢您的回答,经过大量调试我发现openssl DLL加载正确,错误在程序的其他地方。【参考方案2】:MSDN 上的 Dynamic-Link Library Search Order 讨论了图书馆搜索顺序。
有几种方法可以处理加载库,但听起来大部分都不适用。
我不清楚为什么你可以打电话给ChangeCurrentWorkingDirectoryToExeDir
,但你不能打电话给SetDllDirectory
。我可能遗漏了一些明显的东西。
您的最后一个选择似乎是创建一个Qt.exe.local
文件。这称为Dynamic-Link Library Redirection,将导致链接器加载本地文件中指定的 DLL。
【讨论】:
我认为这不适用于这种情况,因为 SSL 是在运行时加载的,而不是在应用程序加载时加载的。这可以使用 Dependency Walker 来确认。我可以使用没有可用的 libeay32.dll/ssleay32.dll 的 Qt Network 正确启动应用程序,这会导致运行时警告,例如QSslSocket: cannot call unresolved function SSL_library_init
。以上是关于强制 Qt5 从 exe 目录加载 SSL dll的主要内容,如果未能解决你的问题,请参考以下文章
在windows下安装了QT creator 编译出来的.exe文件 双击无法执行,提示找不到:没有找到qt5cored.dll
Qt5 编译.exe成品, 将.exe和一堆.dll合成一个.exe进行发布
Qt官方开发环境生成的exe发布方式--使用windeployqt(windeployqt是单独的程序,放在低版本qt4目录下也可以运行的)