By now Windows XP is getting a bit long in the tooth and Microsoft has dropped support for it. Windows 2003, though, is still supported by Microsoft. If you’ve using Qt together with Visual Studio (and not the MinGW compiler) and you try deploying your app to a Windows XP or Windows Server 2003 computer, chances are you’re seeing this error:
This error will not occur for Qt with Visual Studio 2010, but it will when using Visual Studio 2012, 2013 or Visual Studio 2015.
Update thanks to comment below: (use QMAKE_LFLAGS_WINDOWS instead of tweaking the project’s setting): There are basically two ways to fix this; the easy way is to add one extra line to your project’s .pro file, or you can be more adventurous and binary-patch your app’s .exe file.
And yes, this has to be applied for every app you develop, until XP is gone gone gone…
Note: This same error (“.. not a valid Win32 application.”) occurs if you try to start a 64-bit app on a 32-bit Windows XP or Windows 2003 system, so make sure your app is really 32-bit flavored. One way to verify the bitness: launch your app in Windows 7 or 10, start Task Manager, in the process tab check that your app’s name has a “* 32” suffix.
Also: This tweaking do not affect or disturb deployment to other, later Windows versions like Windows 7. (In case you’re targeting multiple Windows versions.) I have verified this works on Windows XP Service Pack 3 and Windows Server 2003 Service Pack 1 and 2 systems.
Let’s take them in order:
Open the .pro file for your project and insert this line (I usually do it at the end):
QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS,5.01
Why 5.01? Well if you look at the original settings, using for example
dumpbin/headerson your .exe file, you see that the SUBSYSTEM:WINDOWS version is set to 6. This means it can run on Windows Vista and later and why Windows XP rejects it. By changing it to 5, we declare XP and Win2k3 as kosher chaps too. (Those numbers 5 and 6 are the internal Windows version numbers.)
I thought originally it should be enough to specify /SUBSYSTEM:WINDOWS,5 but then the linker complains: LNK4010: invalid subsystem version number, and it resets it back to 6 🙁 So 5.01 it is.
Note: if you’re compiling a 64-bits flavored .exe file (and thus targeting 64-bits Windows XP) you instead should set <VALUE> to /SUBSYSTEM:WINDOWS,5.02
I promised you a more thrilling choice as well, it requires you to have a binary/hex file editor. Open your app’s .exe file with it, go to almost the beginning of the file, you’ll see something along the following lines:
Look for the hex sequence 06 00 00 00 00 00 00 00 (repeated one time). In my example above it’s on address 0000130 but it can be slightly different like 0000128 or 0000140.
There’s two consecutive series, change both of them to 05 00 01 00 00 00 00 00.
This binary editing is equivalent to the linker setting I mention above, but actually it suffices to change the two 06 numbers to 05. However, the linker complained when I tried SUBSYSTEM:WINDOWS,5, so let’s humor Microsoft here and set the binary numbers equivalent to SUBSYSTEM:WINDOWS,5.01
Note: if this a 64-bit .exe file, you’re supposed to instead change to 05 00 02 00 00 00 00 00 (two times).
Save the .exe file, Windows XP and Win2k3 server should run the file fine.
Q: “By setting those values, you’re declaring my app and Qt to be fully compatible with Windows XP. How can you be sure of this?”
While I’m not 100% sure, I think Qt does not depend on any feature(s) introduced in Windows Vista or later. (If you’re targeting WinRT Qt has an option to support it, but that’s another story.)
But of course, if your own code depends on other such new stuff, then deployment to Windows XP won’t work.
Also note: the other compiler for Qt in Windows, MinGW, declares apps to be compatible even back to Windows NT4 SP4, because MinGW sets the SUBSYSTEM:WINDOWS value to 4.0. So chances are pretty high no part of Qt (as yet) fails on Windows XP or Server 2003.
Q: “I did exactly what you said, but my app still fails on Windows XP with this error:”
This happens if you’re running the RTM version of Visual Studio 2012. Install the Visual Studio 2012 Update 4 and you should be fine.
Q: “I installed Update 4, however my app still fails on Windows XP with the same error as above :-(“
This happens if you’re using VS2012 Qt 5.3 or later: even though you’ve applied Update 4 to VS2012, the ICU DLLs
icuuc52.dll were unfortunately built using VS2012 RTM (i.e. no Update 4 was applied), here’s a bug report, it also contains a workaround.
Q: “I also did just as you said, but my app fails anyway on Windows XP, now showing this error:”
This error can occur for either Visual Studio 2012 or 2013, it’s instead related to what flavor of the Platform SDK you have installed, e.g. Windows SDK 8.x instead of Windows SDK 7.1. More info about this can be found here: How to target XP …
TL;DR: to fix this error, define the environment variable
_ATL_XP_TARGETING in your project and rebuild.
Thanks to user
theysoar on the Qt Project forums for the screen shot!
Q: “Why don’t I have to apply this procedure when I am using the MinGW or the Visual Studio 2010 compilers?”
There isn’t any clear-cut technical explanation for this; while Microsoft did tweak the C runtime startup code between Visual Studio 2010 and 2012, and dropped support for XP deployment, they quickly had to back-pedal and release an update that reinstated XP as a valid target, instead requiring this linker setting or patching. I guess we can blame it on the internal political struggles at Microsoft 🙂
Next up: deploying a real application.