c++ win32 prevent application from running on windows xp
I've developed a application which uses Vista (or higher) API's and i would 开发者_开发问答like to add a popup message if the application detects a unsupported OS.
I would like to add a popup message when a user runs my application on windows XP. Currently the application just throws a popup(messageBox) saying that some DLL's can't be loaded.
I've defined the windows version like this:
#define _WIN32_WINNT 0x0600
What do i have to do to prevent from running on versions lower than Vista? Do i have to check the OS version when the application starts (and show a message to the user)?
If you are using APIs that are not available on XP, you will need to separate your application into a loader and the real app (or a loader and a DLL containing the actual app). Compile the loader with #define _WIN32WINNT 0x0501
to ensure that it can run on XP and display your popup.
Check the version with VerifyVersionInfo or GetVersionEx
In order to show a popup message, you need to run the executable. That means that you have to reduce your windows version to the lowest one you intend to 'support' (support here meaning be able to run at, and show a popup saying that it won't run). That would require you to delay the point were you link to your relevant DLLs, otherwise they won't be found and you would still get the same message box you do know.
All in all, there are numerous drawbacks with this approach since you have to build a valid executable both at XP as well as Vista. If you really need this check, then you could have one executable do it and decide whether to show a popup message or start your actual application (in a different executable).
You could write a very small wrapper app that defines _WIN32_WINNT as 0x0501. Then that program can do an OS check and either display some nice UI for your user (if it is the wrong version of Windows) or just quietly launch your other executable (if it is a supported version of Windows).
Ideally your distribution channel (website, etc) would check that the user has a supported version of windows before allowing them to download it.
If you use WiX (or MSI directly) to install your app, you can let the installer handle the unsupported OS check.
You cannot expect dynamic runtime behavior if you enforce static compile time behavior. You need to define the XP windows version so that your exe linkg against the XP DLLs, and then at runtime you need to dynamically change the behavior and load the Vista DLLs and find the entry points 'by hand'. This is, as you'd expect, painful and error prone. Good luck.
You can define _WIN32_WINNT
to a lower value, suitable for 2000 or XP. But then you will need to use explicit linking for Vista only APIs. Changing _WIN32_WINNT
will also result in missing type declarations for the Vista only APIs. So, if you know which APIs you need you could leave _WIN32_WINNT
at 0x0600
and use explicit linking for those APIs. Obviously you would need a version check too to give a helpful message to the user.
Personally I'd take a different route to solving this. I'd check the version at install time and block it there. That allows you to carry on with _WIN32_WINNT 0x0600
and all the conveniences that affords.
What's happening is the DLLs are being loaded by the application loader and you are seeing the error messages before your application even starts. You need to prevent this from happening.
You could put your application into a DLL and create a stub program that performs the OS check like Mystical describes in his answer.
Edit:
It seems Mystical deleted his answer... Do something like this:
OSVERSIONINFO OSversion;
OSversion.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
::GetVersionEx(&OSversion);
switch(OSversion.dwPlatformId)
{
case VER_PLATFORM_WIN32_NT:
if(OSversion.dwMajorVersion >= 6)
{
// Yay, load the DLL and call entry point
}
default:
// Show unsupported OS message
}
You can call LoadLibrary()
to load your application DLL then call whatever entry point in it you defined.
Note this answer has a cool list of OS version numbers.
I don't know how to do this in Visual Studio or other compilers, but in Borland/CodeGear/Embarcadero IDEs, there is an option to set the minimum supported OS version in the compiled executable's PE header. If the OS loader tries to run an executable with an incompatible version, it will not run the executable and will display an error message to the user about the version mismatch. Check if your compiler/IDE has a similar option available.
Otherwise, you have to dynamically load the desired APIs at runtime via LoadLibrary()
/GetModuleHandle()
and GetProcAddress()
instead of statically linking to them at compile time. Then you can perform your own OS version checks in your code before using newer API functions that may not be available.
精彩评论