在 64 位 Windows 10 上安装适用于 MSVC2017 的 OpenSSL

2022-01-19 00:00:00 qt openssl qml get javascript

.pro

LIBS += -LC:QtToolsOpenSSLWin_x86lib -llibssl
LIBS += -LC:QtToolsOpenSSLWin_x86lib -llibcrypto
INCLUDEPATH += C:QtToolsOpenSSLWin_x86include

ma​​in.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.0

Window {
    visible: true
    width: 640
    height: 480

    Component.onCompleted: getPage(logResults)

    function logResults(results) {
        console.log("RESULTS: " + results)
    }

    function getPage(callback) {
        var xhttp = new XMLHttpRequest();
        var url = "https://www.google.com/"

        xhttp.onreadystatechange = function() {
            if (xhttp.readyState === 4 && xhttp.status === 200) {
                console.log("calling callback")
                callback(xhttp.responseText)
            }
        };
        xhttp.open("GET", url);
        xhttp.send();
    }
}

预期输出

qml: calling callback
qml: RESULTS: <html>

实际输出

qt.network.ssl: QSslSocket: cannot resolve SSL_CTX_set_ciphersuites
qt.network.ssl: QSslSocket: cannot resolve SSL_set_psk_use_session_callback
qt.network.ssl: QSslSocket: cannot call unresolved function SSL_set_psk_use_session_callback
qml: calling callback

Windows 10 64 位操作系统,运行 MSVC2017 QML 项目

我运行 C:QtMaintenanceTool.exe 来安装 Developer and Designer Tools >OpenSSL 1.1.1d 工具包

我已尝试遵循 之前的教程和另一个 MSVC2017 但在解决错误或获得 <代码>xhttp.responseText.发现 代码在 ubuntu 19.4 中工作 所以它必须是我我在我的 Windows 机器上运行它,OpenSSL 正在发生一些奇怪的事情.通过谷歌搜索输出的错误消息,我找不到任何解决方案.我读过不小心将 openSSL 安装到windows 目录"会导致错误,但我无法真正找到有问题的windows 目录"来检查我是否这样做了.

I've tried following a previous tutorial and another one for MSVC2017 but no luck in resolving the errors or getting xhttp.responseText. Found out the code works in ubuntu 19.4 so it just has to be that I'm running it on my windows machine that something funky is happening with the OpenSSL. I couldn't find any resolution by googling the outputted error messages. I've read that accidentally installing openSSL to "the windows directory" can cause errors, but I've not been able to actually locate "the windows directory" in question to check if I did.

编辑

C:QtToolsOpenSSLWin_x64in 我复制了 libcrypto-1_1-x64.dlllibssl-1_1-x64.dll 到我项目的 debugelease 文件夹.这消除了 qt.network.ssl 错误,但是我仍然没有得到 qml: RESULTS: <html>

From C:QtToolsOpenSSLWin_x64in I copied libcrypto-1_1-x64.dll and libssl-1_1-x64.dll to my project's debug and elease folders. This removed the qt.network.ssl errors, however I am still not getting the expected output of qml: RESULTS: <html>

推荐答案

您运行 C:QtMaintenanceTool.exe 来安装 Developer 和 Designer工具 > OpenSSL 1.1.1d 工具包

You ran C:QtMaintenanceTool.exe to install Developer and Designer Tools > OpenSSL 1.1.1d Toolkit

这也是我的建议.另一种方法是自己编译 OpenSSL,或者从第三方提供商处下载二进制包.我在 "C:Program FilesOpenSSL-Win64in" 安装了其中一个包,使用 Qt+=network 的程序能够找到并加载库当他们的路径包含在 PATH 环境变量中时.问题是您需要自己处理更新,但是 Qt 包会使用 MaintenanceTool 以及 Qt 和 Qt Creator 自动更新.所以选择你的选择.

That is also my recommendation. The alternative is to compile OpenSSL yourself, or download a binary package from a third party provider. I have one of those packages installed at "C:Program FilesOpenSSL-Win64in", and programs using Qt+=network are able to locate and load the libraries when their path is included in the PATH environment variable. The problem is that you will need to take care of the updates yourself, but the Qt packages are automatically updated with the MaintenanceTool along with Qt and Qt Creator. So pick your choice.

无论如何,即使您的路径中有另一组 OpenSSL DLL,如果您将这些库复制到可执行文件的输出目录,这些库也会被加载.这里需要回答两个问题:1)如何在每次需要 DLL 时自动复制它们?2)在运行程序时如何验证加载了哪些 DLL?

Anyway, even if you have another set of OpenSSL DLLs in your path, if you copy the libraries to the output directory of your executable, these libraries will be loaded instead. Two questions need to be answered here: 1) how do you copy the DLLs automatically each time they are needed?, and 2) how do you verify which DLLs are loaded when you run your program?

1) 您可以将以下内容添加到您的项目 .pro 中:

1) You may add the following to your project .pro:

win32 {
    CONFIG += file_copies
    CONFIG(debug, debug|release) {
        openssllibs.path = $$OUT_PWD/debug
    } else {
        openssllibs.path = $$OUT_PWD/release
    }
    contains(QMAKE_TARGET.arch, x86_64) {
        openssllibs.files = C:/Qt/Tools/OpenSSL/Win_x64/bin/libcrypto-1_1-x64.dll 
                            C:/Qt/Tools/OpenSSL/Win_x64/bin/libssl-1_1-x64.dll
    } else {
        openssllibs.files = C:/Qt/Tools/OpenSSL/Win_x86/bin/libcrypto-1_1.dll 
                            C:/Qt/Tools/OpenSSL/Win_x86/bin/libssl-1_1.dll
    }
    COPIES += openssllibs
}

就是这样.现在,您的程序将始终将 Qt/Tools 中的最新库复制到项目的输出目录中,而无需担心您是否在调试或发布模式、32/64 位或其他 Qt 工具包中编译.

That is it. Now your program will always have the latest libraries from Qt/Tools copied to the output directory of your project, without worrying if you compile in debug or release mode, or 32/64 bits, or another Qt Kit.

2) 在使用 Process Explorer 检查加载的 DLL 时运行程序,作者 Mark Russinovich.为此,请在 Process Explorer->View->Show lower pane 中,然后在上部窗格中选择正在运行的程序.下部窗格列出了所有加载的 DLL 和来源.还有其他类似的实用程序,例如开源 Process Hacker.

2) Run your program while inspecting the loaded DLLs with Process Explorer, by Mark Russinovich. To do so, in Process Explorer->View->Show lower pane, and select your running program in the upper pane. The lower pane lists all your loaded DLLs and origins. There are other similar utilities out there, like the open source Process Hacker.

即使了解以上所有内容,并完全按照配方进行操作,您的程序仍然无法打印所需的输出.请像这样更改 qml 中的函数 logResults():

Even understanding all of the above, and following exactly the recipe, your program still does not print the desired output. Please change the function logResults() in your qml like this:

function logResults(results) {
    console.log("RESULTS Length=", results.length);
    console.log("results.substr=", results.substr(0, 20)); 
}

你会得到以下输出:

qml: calling callback
qml: RESULTS Length= 47932
qml: results.substr= <!doctype html><html

说明:看起来 console.log() 在 Windows 中的限制约为 32K(在 Linux 上没有).从远程主机检索到的文档要大得多,这会破坏日志记录功能.这可能是 Qt 中的一个错误(它不应该像那样默默地失败).

Explanation: looks like console.log() has a limitation of about 32K in Windows (it doesn't on Linux). The document retrieved from the remote host is much larger, and this breaks the logging function. This is probably a bug in Qt (it should not fail silently like that).

对将来来到这里的任何人的另一个建议:它不是严格需要的,但您可能希望在您的 main() 函数中验证 SSL 是否可用,类似于以下代码:

Another advice for anybody coming here in the future: It is not strictly needed, but you may want to verify in your main() function that SSL is available, with something like this code:

#include <QDebug>
#include <QSslSocket>

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    if (!QSslSocket::supportsSsl()) {
       qDebug() << "Sorry, OpenSSL is not supported";
       return -1;
    }
    qDebug() << "build-time OpenSSL version:" << QSslSocket::sslLibraryBuildVersionString();
    qDebug() << "run-time OpenSSL version:" << QSslSocket::sslLibraryVersionString();
    [...]
}

相关文章