28

How I can check in C++ if Windows version installed on computer is Windows Vista and higher (Windows 7)?

Matej
  • 283
  • 1
  • 3
  • 4
  • See: http://stackoverflow.com/questions/741294/windows-version-identification-c-c and also: http://stackoverflow.com/questions/57124/how-to-detect-true-windows-version – Shog9 Dec 28 '09 at 17:38

7 Answers7

30

All the answers in this thread point you to using GetVersion or GetVersionEx for this test, which is incorrect. It seems to work, but it is risky. The primary source of appcompat problems for Windows OS upgrades comes from poorly written tests based on GetVersion results with bad assumptions or buggy comparisons.

The correct way to do this test is to use VerifyVersionInfo, not GetVersion or GetVersionEx.

If you are using the VS 2013 compiler toolset and the Windows 8.1 SDK, you can use the VersionHelpers.h and just call IsWindowsVistaOrGreater.

If you are using the VS 2013 v120_xp platform toolset to target Windows XP, you are actually using the Windows 7.1A SDK, so you need to use VeriyVersionInfo directly.

Otherwise, use:

bool IsWindowsVistaOrGreater()
{
OSVERSIONINFOEXW osvi = {};
osvi.dwOSVersionInfoSize = sizeof(osvi);
DWORDLONG const dwlConditionMask = VerSetConditionMask(
    VerSetConditionMask(
    VerSetConditionMask(
            0, VER_MAJORVERSION, VER_GREATER_EQUAL),
               VER_MINORVERSION, VER_GREATER_EQUAL),
               VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
osvi.dwMajorVersion = HIBYTE(_WIN32_WINNT_VISTA);
osvi.dwMinorVersion = LOBYTE(_WIN32_WINNT_VISTA);
osvi.wServicePackMajor = 0;

return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
}

This code will work on Windows 2000 or later and give you a robust result. If you really needed this test to run on Windows 98 or Windows ME -and- you are using a compiler toolset old enough to actually run on that platform, you'd do the same test but with explicit rather than implicit linking. What's in a version number?

Furthermore, using GetVersion or GetVersionEx will by default get the wrong version on Windows 8.1 and Windows 10. See Manifest Madness.

Note that with Windows 10 VerifyVersionInfo is also subject to the same manifest-based behavior (i.e. without the GUID element for Windows 10, VVI acts as if the OS version number is 6.2 rather than 10.0. That said, most real-world tests like IsWindowsVistaOrGreater, IsWindows7OrGreater, IsWindows7SP1OrGreater, IsWindows8OrGreater are all going to work just fine even without the manifest. It's only if you are using IsWindows8Point1OrGreater or IsWindows10OrGreater that the manifest-based behavior even matters.

See also this stack overflow thread.

Chuck Walbourn
  • 38,259
  • 2
  • 58
  • 81
  • 1
    I agree that `VerifyVersionInfo` is the right answer for the OP. It would always be right if I wanted to ask the question: `Is the current Windows version at least good enough for my minimum needs?` (as the OP does) But the question I _really_ want to answer is `What is the current Windows version?` so I can display it. – Jesse Chisholm Dec 16 '16 at 20:34
  • For purely telemetry/support display purposes: In Windows desktop apps, you use ``GetVersionEx``, suppress the deprecation warning, add the compatibility manifest to your EXE, and know that someday it will likely lie. With Universal Windows Platform apps (UWP), you'd use [AnalyticsInfo](https://msdn.microsoft.com/en-us/library/windows/apps/windows.system.profile.analyticsinfo.aspx). In both cases, don't base any logic at all on the value of the version number or perform any comparisons. If it's for phone support, just tell the user to run ``winver`` and read the string back to you. – Chuck Walbourn Dec 16 '16 at 20:46
  • Agreed! But such hoops one must jump through to answer such a simple question (that used to be easy to ask). – Jesse Chisholm Jan 05 '17 at 07:00
  • It was always easy to ask "what version of Windows is this?". The harder problem was (a) asking the right question, and (b) knowing what to do with the answer. People screwed this up writing apps for Windows 3 in the early 90s, so it's *always* been challenging to get it right. See [this blog post](https://blogs.msdn.microsoft.com/oldnewthing/20040213-00/?p=40633/). With "Windows as a service", the question is also not quite as meaningful as it once was. – Chuck Walbourn Jan 05 '17 at 07:21
  • "was" being the important word - it is now hard. And in my case, the purpose is to _display_ the Windows Version, I make no decisions based on the value. I understand that changing how it is done is to make it harder to ask the wrong question. But I wasn't asking the question for that decision making purpose. – Jesse Chisholm Jan 23 '17 at 14:53
  • "[GetVersionEx may be altered or unavailable for releases after Windows 8.1. Instead, use the Version Helper functions]" per MSDN.. and it's also flagged for deprecation in msvc141 so kudos for this answer. Personally i'd rather have them both available. – Crypth Apr 12 '18 at 19:47
  • Remember that the warning is really there to get you to look at it at build time instead of making you discover it at runtime. You can either remove the use of the version check API (and replace it with something that's better for appcompat like a QueryInterface test) or suppress the warning and add the manifest entries needed to make it actually work (ideally using ``VerifyVersionInfo`` or the VersionHelpers wrappers for 'you must be this high to ride this ride' tests instead of error-prone conditionals using ``GetVersionEx``) – Chuck Walbourn Apr 12 '18 at 19:54
20

Use GetVersionEx API function defined in kernel32.dll:

bool IsWindowsVistaOrHigher() {
   OSVERSIONINFO osvi;
   ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
   GetVersionEx(&osvi);
   return osvi.dwMajorVersion >= 6;
}
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
18

Similar to other tests for checking the version of Windows NT:

OSVERSIONINFO   vi;

memset (&vi, 0, sizeof vi);
vi .dwOSVersionInfoSize = sizeof vi;
GetVersionEx (&vi);
if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT  &&  vi.dwMajorVersion >= 6)
wallyk
  • 56,922
  • 16
  • 83
  • 148
  • 2
    Why must the platform be 32-bit? – Drew Dormann Dec 26 '09 at 22:12
  • It needs to be sure it isn't 16 bit windows 95/98/ME or Win32s for MajorVersion not to be confused. I suppose it should allow WIN64 as well, but I can't find the macro name. – wallyk Dec 26 '09 at 23:50
  • 5
    64 bit Windows has platform ID of VER_PLATFORM_WIN32_NT – David Heffernan Jun 13 '11 at 16:41
  • @David: thanks. That explains why I couldn't find a 64 bit value. – wallyk Jun 13 '11 at 17:32
  • 2
    This is no longer true. Unless you manifest your application to be Windows-8.1(and above)-aware, `GetVersionEx` will lie to you. This is outlined in [Chuck Walbourn's answer](http://stackoverflow.com/a/27324801/1889329). – IInspectable Dec 02 '15 at 23:05
  • @IInspectable: Thanks. Maybe you should post another answer. When I wrote this 4.5 years ago, it *was* true. – wallyk Dec 03 '15 at 01:07
  • There are others APIs that can retrieve the true OS version number without requiring manifestation, namely `RtlGetVersion()`, `NetServerGetInfo()`, and `NetWkstaGetInfo()` have all been tested and proven to work. – Remy Lebeau Dec 03 '15 at 01:33
  • @wallyk: There was a 16bit version of Windows ME? – Kaiserludi Jan 20 '16 at 19:30
  • @Kaiserludi: Yes, that was how it was [originally released](https://en.wikipedia.org/wiki/Windows_ME). – wallyk Jan 20 '16 at 21:13
  • @wallyk: the linked article does not mention anything about 16bit at all - however https://en.wikipedia.org/wiki/History_of_Microsoft_Windows#Windows_95 mentions that even Windows 95 already only preserved WIN16 for backwards compatibility. If I understand that article correctly, then even Windows 95 already was not available as 16bit OS anymore, but only as 32bit OS that could still run 16bit programs similar to todays 64bit OS being able to run 32bit programs. That would match my memory. – Kaiserludi Jan 21 '16 at 13:35
  • Sadly, `GetVersionEx` was deprecated in W8, in favor of `VerifyVersionInfo`, which doesn't fill in the current values, merely tests your needs against the current values. – Jesse Chisholm Dec 16 '16 at 20:31
  • @JesseChisholm: Sheesh. One of Microsoft's most annoying philosophies is that they intentionally force change and obsolescence. Instead of providing backwards compatibility for features which could be sustained indefinitely. Note that 7 years ago, when I wrote the answer, it was fully supported. – wallyk Dec 16 '16 at 21:12
  • 1
    @wallyk - Totally agreed on the annoying factor of Microsoft decision making. The new functionality in `VerifyVersionInfo` is good and useful, but there was no need to deprecate `GetVerionEx`. – Jesse Chisholm Jan 05 '17 at 06:54
  • 1
    Actually, the code you wrote in this answer is exactly *why* the Microsoft appcompat team pushed to deprecate ``GetVersionEx`` in the first place. Major applications have done this and gotten it wrong since Windows 95. If you want to make a 'you must be this high to ride this ride' check, that's what ``VerifyVersionInfo`` is designed to do robustly and correctly (which is also what the VersionHelpers API wrappers use). As my answer notes, you should be aware that as of Windows 10 VVI has the same manifest-based behavior so you need to plan to add the manifests as well. – Chuck Walbourn Apr 12 '18 at 20:01
13

In Visual Studio 2013 or higher, you can also use the new Version Helper functions.

There are methods for many different Windows versions. Example:

#include <VersionHelpers.h>

if (!IsWindowsVistaOrGreater())
{
   MessageBox(NULL, "You need at least Windows Vista", "Version Not Supported", MB_OK);
}

More information here

Hiale
  • 924
  • 1
  • 9
  • 10
  • 1
    This is a great option if using VS 2013 and the Windows 8.1 SDK, as long as you are not trying to target Windows XP with the ``v120_xp`` platform toolset which is actually using the Windows 7.1A SDK. There's nothing special about ``VersionHelpers.h`` as it's just utility code for using ``VerifyVersionInfo`. – Chuck Walbourn Dec 05 '14 at 21:17
  • this should be marked as correct answer, because it's directly offered by Windows SDK. Beware, for Windows 10 and 8.1 you need an application manifest https://msdn.microsoft.com/de-de/library/windows/desktop/ms725492%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 – madduci Oct 18 '16 at 08:31
6

I think you're looking for the GetVersionEx function.

Adam Maras
  • 26,269
  • 6
  • 65
  • 91
4

This Microsoft support page gives you details for older versions.

To determine the operating system that is running on a given system, the following data is needed:

              95  98  ME  NT 4  2000  XP
PlatformID    1   1   1   2     2     2
Major version 4   4   4   4     5     5
Minor version 0   10  90  0     0     1

You could implement the code and run it on a Vista and Windows-7 machine to check the values returned.

To get the operating system version information make the following call:

System::OperatingSystem *osInfo = System::Environment::OSVersion;
Community
  • 1
  • 1
ChrisF
  • 134,786
  • 31
  • 255
  • 325
1

You could use the GetVersion() or GetVersionEx() function in the kernel32.dll. This two functions are only available on Windows 2000 or later.

To read more about this look at http://msdn.microsoft.com/en-us/library/ms724451%28VS.85%29.aspx.

jpyllman
  • 307
  • 2
  • 6