强制 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.dllssleay32.dll(因为它是静态的)。

(详情:位于qtbase\src\network\ssl\qsslsocket_openssl_symbols.cpp

static QPair<QSystemLibrary*, QSystemLibrary*> loadOpenSslWin32()

)

问题:

我的程序不是以 exe 目录作为工作目录开始的 libeay32.dllssleay32.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::loadonlySystemDirectory = false 一起调用 SSL,因此 QFileInfo(qAppFileName()).path() 是搜索 DLL 的第一个位置。搜索顺序:

    应用程序目录 系统路径(例如 C:\Windows\System32) PATH 中的所有路径

我没有找到这方面的文档,但在我们的软件中,当 SSL libeay32.dllssleay32.dll 与应用程序 .exe 位于同一目录中时,Qt 会发现它们

.dll 文件不在 PATH 中 .dll 文件不在工作目录中 不存在qt.conf

如果您有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

qtqws运行一段时间没键盘

vs2010+qt5.40离线exe中dll配置

Qt5 编译.exe成品, 将.exe和一堆.dll合成一个.exe进行发布

Qt官方开发环境生成的exe发布方式--使用windeployqt(windeployqt是单独的程序,放在低版本qt4目录下也可以运行的)

QT生成可执行的EXE程序