Compile binary works standalone, doesn't from QtCreator (Windows API)
-
Good afternoon,
again I need your help since I am missing something obvious here.After quite a while I am forced to program for Windows (10, current) and I failed miserably. (Stack is my usual: Win10, Mingw-x64, Qt 15.2)
I need to write a tool that sends ICMP packets. Nothing big but since QNAM doesn't support ICMP I am forced to rely on WinAPI - I have to admit that Windows API isn't one of my strong points.So, I took a look here https://docs.microsoft.com/en-us/windows/win32/api/icmpapi/nf-icmpapi-icmpsendecho - there is a sample code. I decided to take it as a prototype, just to find out if it works for me or no.
It compiled, but obviously failed to start from the QtCreator due to lack of libraries on the path, as expected. I used dependency walker and patience - and got to the point where standalone, deployed with windeployqt program starts and works. So I copied over external libraries to the debug folder so I can run the debug (worked with Poppler and other external libs I worked with on Windows) - but program crashes on startup, with no trace at all. Mind you, this is just a stub program, main window and test method to test WinAPI call.To make it run as standalone, besides usual windeployqt stuff, I had to copy over:
- hvsifiletrust.dll (from windows/system32)
- IEShims.dll (from Program Files/Internet Explorer)
- SHCore.dll (from windows/system32)
- shlwapi.dll (from windows/system32)
I totally fail to understand why some dlls from windows32 (like included Iphlpapi.dll and w2_32.dll) are accessible for the program and some not, to add to it. So - the program runs standalone, copying those above to the debug folder to be with .exe doesn't work, program doesn't even enter the main loop.
Below is excerpt from my source, can someone smack me in the head and explain what do I miss?
Please?- .pro file:
INCLUDEPATH += "C:/Program Files/mingw-w64/x86_64-8.1.0-win32-seh-rt_v6-rev0/mingw64/x86_64-w64-mingw32/include" DEPENDPATH += "C:/Program Files/mingw-w64/x86_64-8.1.0-win32-seh-rt_v6-rev0/mingw64/x86_64-w64-mingw32/include" LIBS += -L'C:/Program Files/mingw-w64/x86_64-8.1.0-win32-seh-rt_v6-rev0/mingw64/x86_64-w64-mingw32/lib/' -liphlpapi INCLUDEPATH += 'C:/Program Files/mingw-w64/x86_64-8.1.0-win32-seh-rt_v6-rev0/mingw64/x86_64-w64-mingw32/include' DEPENDPATH += 'C:/Program Files/mingw-w64/x86_64-8.1.0-win32-seh-rt_v6-rev0/mingw64/x86_64-w64-mingw32/include' LIBS += -L'C:/Program Files/mingw-w64/x86_64-8.1.0-win32-seh-rt_v6-rev0/mingw64/x86_64-w64-mingw32/lib/' -lws2_32
- code:
#include <QObject> #include <winsock2.h> #include <iphlpapi.h> #include <icmpapi.h> bool TestingClass::runICMP(const QString &host) { HANDLE hIcmpFile; unsigned long ipaddr = INADDR_NONE; DWORD dwRetVal = 0; char SendData[32] = "Data Buffer"; LPVOID ReplyBuffer = NULL; DWORD ReplySize = 0; ipaddr = inet_addr(host.toUtf8().constData()); hIcmpFile = IcmpCreateFile(); if (hIcmpFile == INVALID_HANDLE_VALUE) { emit error("\tUnable to open handle.\nIcmpCreatefile returned error: %ld\n"+QString::number(GetLastError())); return false; } ReplySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData); ReplyBuffer = (VOID*) malloc(ReplySize); if (ReplyBuffer == NULL) { emit error("\tUnable to allocate memory\n"); return false; } dwRetVal = IcmpSendEcho(hIcmpFile, ipaddr, SendData, sizeof(SendData), NULL, ReplyBuffer, ReplySize, 1000); if (dwRetVal != 0) { PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer; struct in_addr ReplyAddr; ReplyAddr.S_un.S_addr = pEchoReply->Address; if (dwRetVal > 1) { qDebug() << "\tReceived %ld icmp message responses\n" << dwRetVal; } else { qDebug() << "\tReceived %ld icmp message response\n" << dwRetVal; } qDebug() << "\t Received from %s\n" << inet_ntoa( ReplyAddr ) ; qDebug() << "\t Status = %ld\n" << pEchoReply->Status; qDebug() << "\t Roundtrip time = %ld milliseconds\n" << pEchoReply->RoundTripTime; return true; } else { qDebug() << "\tCall to IcmpSendEcho failed.\n" << "\tIcmpSendEcho returned error: %ld\n", GetLastError(); return false; } return false; }
Many thanks in advance.
-
@artwaw said in Compile binary works standalone, doesn't from QtCreator (Windows API):
To make it run as standalone, besides usual windeployqt stuff, I had to copy over:
Don't do that. Use the system provided libraries. If you want to make it really "standalone" you'd need to link against a static runtime, however I'm not sure if the windows SDK provides one. ( @Chris-Kawa may be more up to date ).
It compiled, but obviously failed to start from the QtCreator due to lack of libraries on the path, as expected.
The libraries should already be in the path, so it should run from Creator. This isn't some external dll, this is part of the windows kernel.
-
@artwaw said in Compile binary works standalone, doesn't from QtCreator (Windows API):
To make it run as standalone, besides usual windeployqt stuff, I had to copy over:
hvsifiletrust.dll (from windows/system32) Part of Windows Defender
IEShims.dll (from Program Files/Internet Explorer)
SHCore.dll (from windows/system32)
shlwapi.dll (from windows/system32)Those files are a standard part of any Windows 10 installation and should not be redistributed (copyright violation I suspect). IIRC IEShims.dll always shows as a problem in Dependency Walker and has never caused an issue to me. As useful as DW is, it generates quite a few "normal" errors these days.
Your original problem is elsewhere.
Based on your PRO file paths, you appear to be using your own MingW toolchain for at least part of this build.
Did you build your own Qt libs and QtCreator with your tool chain, or are you using the binary distribution? -
Thank you for the input.
@kshegunov said in Compile binary works standalone, doesn't from QtCreator (Windows API):
The libraries should already be in the path, so it should run from Creator. This isn't some external dll, this is part of the windows kernel.
That was my assumption at first...
@ChrisW67 said in Compile binary works standalone, doesn't from QtCreator (Windows API):
Based on your PRO file paths, you appear to be using your own MingW toolchain for at least part of this build.
Did you build your own Qt libs and QtCreator with your tool chain, or are you using the binary distribution?I have MinGW both from Qt (installed via online installer, in Qt folder tree) and standalone form MSys2 - they are not mixed.
But Qt MinGW does not provide the necessary headers while the Msys2 does.
I used headers and lib files from MSys2 as this has worked for me in the past - my previous project involved Poppler, which I built using Msys2 and linked to Qt 15.2 dynamically without any problems.If I try WinSDK would it work with MinGW? I am in dark here.
-
I switched to WinSDK, updated .pro file:
INCLUDEPATH += "C:/WinSDK/10/Include/10.0.19041.0/um" DEPENDPATH += "C:/WinSDK/10/Include/10.0.19041.0/um" LIBS += -L"C:/WinSDK/10/Lib/10.0.19041.0/um/x64" -liphlpapi LIBS += -L"C:/WinSDK/10/Lib/10.0.19041.0/um/x64" -lws2_32
Qt complained about missing
kernelspecs.h
file, which I found here:INCLUDEPATH += "C:/WinSDK/10/Include/10.0.19041.0/shared"
Also, header files case changed to:
#include <WinSock2.h> #include <iphlpapi.h> #include <IcmpAPI.h>
Right now when try to build I get tons of errors:
C:\WinSDK\10\Include\10.0.19041.0\shared\sdkddkver.h:292: error: #error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting In file included from C:\WinSDK\10\Include\10.0.19041.0\um/windows.h:22, from C:\Qt\5.15.2\mingw81_64\include/QtCore/qt_windows.h:64, C:\WinSDK\10\Include\10.0.19041.0\shared/sdkddkver.h:292:2: error: #error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting #error NTDDI_VERSION setting conflicts with _WIN32_WINNT setting ^~~~~
being the first two, then over a hundred lines like this:
(pardon the screenshot)
So what can I do to fix it (apart from switching to MSVC which I rather not do for a single project)? -
@artwaw said in Compile binary works standalone, doesn't from QtCreator (Windows API):
I switched to WinSDK, updated .pro file
Still using MinGW?
I doubt this is going to work... -
@JoeCFD No, I refuse to. I tried once, perfectly healthy code that I maintained for 3 years on MingW didn't even want to compile (it was Qt only, no external libs), I refused to waste my time on Microsoft shenanigans.
Anyway, I got it to work. I was missing one thing in MinGW. For the record:
- to use WinAPI with MinGW (I do it via Msys2) two packages are needed (I was missing the latter):
msys2-w32api-headers
andmsys2-w32api-runtime
. - .pro file in the end looks like I was expecting:
LIBS += -LC:/msys64/usr/lib/w32api/ -liphlpapi LIBS += -LC:/msys64/usr/lib/w32api/ -lws2_32 INCLUDEPATH += C:/msys64/usr/include/w32api DEPENDPATH += C:/msys64/usr/lib/w32api
Thank you everyone who contributed, thanks to your input I was able to trace and find my error. As always, your help is much appreciated.
- to use WinAPI with MinGW (I do it via Msys2) two packages are needed (I was missing the latter):