0

I have a program that reports and/or detects the Windows OS version. It uses GetVersionEx, but Microsoft intentionally broke this API in Windows 8.1 and later to return incorrect version information. (Apparently proper version checking is just too hard for the masses to get right, but that's a rant for another topic.)

I know that I can add a manifest to work around this particular problem, but my question is about "future-proofing" the program.

If a future user runs the program on a newer OS than Windows 10, will GetVersionEx work correctly and report the "real" OS version, even if the program's manifest doesn't include that version's GUID?

Or am I doomed to continually add new GUIDs to the manifest every time a new OS version is released?

Bill_Stewart
  • 22,916
  • 4
  • 51
  • 62
  • 2
    I believe the most hassle-free/future-proof way to query the OS version is to call native API [RtlGetVersion](https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx) (as outlined in [how to detect windows 10 in c++](http://stackoverflow.com/a/36545162/1889329)). – IInspectable May 04 '16 at 20:08
  • @IInspectable: `RtlGetVersion()` is one of several viable ways to get the *true* OS version. WMI, `NetServerGetInfo()` and `NetWkstaGetInfo()` also work, too. – Remy Lebeau May 04 '16 at 20:13
  • I saw those techniques after posting the question. `RtlGetVersion` is probably the easiest way to do what I need. Thanks! – Bill_Stewart May 04 '16 at 20:15
  • 1
    Microsoft's approved method (for logging/diagnostics purposes only!) is to read the version number from a system DLL such as kernel32.dll. See http://stackoverflow.com/a/25986612/886887 – Harry Johnston May 04 '16 at 22:09
  • The nice thing about `RtlGetVersion` is that it's essentially a drop-in replacement for `GetVersionEx` (in fact, I would not be surprised if `GetVersionEx` is simply a wrapper for `RtlGetVersion` under the hood). Thanks for the additional information however. – Bill_Stewart May 04 '16 at 22:26
  • What is the value of knowing that you're running on an OS that didn't exist at the time you wrote the program? Your program can't change its behavior because it doesn't know what to change its behavior *to*. – Raymond Chen May 04 '16 at 22:58
  • 1
    It may be as simple as wanting to display the OS version to the user. – Jonathan Potter May 04 '16 at 23:03
  • @Raymond Chen - the purpose of the program is to tell the user what the actual OS version is. – Bill_Stewart May 05 '16 at 00:12
  • The problem with RtlGetVersion is that calling it from user mode is against the rules. It works, and it will *probably* keep working, and it *probably* won't ever be changed to behave the same way as GetVersionEx, but that's a lot of *probably* for my taste. :-) – Harry Johnston May 05 '16 at 01:55
  • Its not clear why you need to tell the user what version of Windows they are running. Is this for telemetry? For diagnostics? – Raymond Chen May 05 '16 at 02:12
  • It's a small program that can test for, or display, the OS version from the command line. It's essentially a script-friendly way of retrieving one or more members of the `OSVERSIONINFOEX` struct from scripts (handy from, say, a startup or logon script). – Bill_Stewart May 05 '16 at 02:43

1 Answers1

1

If a future user runs the program on a newer OS than Windows 10, will GetVersionEx work correctly and report the "real" OS version, even if the program's manifest doesn't include that version's GUID?

NO, and this is documented behavior:

With the release of Windows 8.1, the behavior of the GetVersionEx API has changed in the value it will return for the operating system version. The value returned by the GetVersionEx function now depends on how the application is manifested.

Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2). Once an application is manifested for a given operating system version, GetVersionEx will always return the version that the application is manifested for in future releases. To manifest your applications for Windows 8.1 or Windows 10, refer to Targeting your application for Windows.

Or am I doomed to continually add new GUIDs to the manifest every time a new OS version is released?

Sadly, YES. The point of version manifestation is to explicitly report the OS version(s) that your app is known to be compatible with. Obviously you can't know ahead of time if it is compatible with future versions. So, whenever a new version is released, you test your app as needed, verify it working (and fix it if needed), and then update the manifest accordingly. Until then, Windows will down-grade itself to behave like the highest OS version that you have reported in your manifest.

You should not be relying on GetVersionEx() to control your app's functionality at runtime anyway. It is fine for reporting the OS version in logs and such (and there are other ways to get the true OS version regardless of manifestation), but don't make decisions based on OS version. For instance, if want to use a given feature that is only available in recent OS versions, don't check the OS version, check for the existence of the feature itself and use it if it is available.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • As noted, I don't use `GetVersionEx` to control application functionality at runtime. I use it to ask the OS what version it is. But thanks for the answer; I will have to re-architect. – Bill_Stewart May 04 '16 at 20:13
  • 1
    Not necessarily. You could simply replace `GetVersionEx()` with [`RtlGetVersion()`](https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx), for instance. It is not (yet?) subject to manifestation. – Remy Lebeau May 04 '16 at 20:18
  • I worded my sentence rather awkwardly. By "re-architect" I meant "update code to use a different API." – Bill_Stewart May 04 '16 at 20:42