1

I'm a developper from the FOSS game 0 A.D. (https://play0ad.com) and I recently realised that our detection of the Windows version was failing for Windows 11, just like it did between Windows 8.1 and Windows 10.

It reports Windows 10.0.22000 which is technically the correct version, but we'd like it to report Windows 11 instead.

Here is the current code we use

We're stuck with the Windows 7 SDK for compatibility reasons.

Easy solution would be to replace

    if (osInfo.dwMajorVersion >= 10)
    {
        stream << "Win" << osInfo.dwMajorVersion;
    }

by

    if (osInfo.dwMajorVersion >= 10)
    {
        if (osInfo.dwMinorVersion > 22000)
            stream << "Win" << 11;
        else
            stream << "Win" << osInfo.dwMajorVersion;
    }

Is there a more robust/future proof solution.

Thanks in advance!

3 Answers3

2

I'm not sure if this will work, but can you give this code a try? It uses the sysinfoapi.h file. According to the docs, it only works on Windows though.

#include <iostream>
#include <sysinfoapi.h>

void print_os_info()
{
    OSVERSIONINFOEX info;
    ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
    info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);

    GetVersionEx((LPOSVERSIONINFO)&info);

    printf("Windows version: %u.%u\n", info.dwMajorVersion, info.dwMinorVersion);
}

int main()
{
    print_os_info();
}

EDIT: Apparently applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2) according the the sysinfoapi.h docs\

EDIT AGAIN: I tried using a $(Filename).exe.manifest file with the contents

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <assemblyIdentity
        type="win32"
        name="Contoso.ExampleApplication.ExampleBinary"
        version="1.2.3.4"
        processorArchitecture="x86"
    />
    <description>Contoso Example Application</description>
    <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
        <application>
            <!-- Windows 10 and Windows 11 -->
            <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
            <!-- Windows 8.1 -->
            <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
            <!-- Windows 8 -->
            <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
            <!-- Windows 7 -->
            <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
            <!-- Windows Vista -->
            <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
        </application>
    </compatibility>
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
        <security>
            <requestedPrivileges>
                <!--
                  UAC settings:
                  - app should run at same integrity level as calling process
                  - app does not need to manipulate windows belonging to
                    higher-integrity-level processes
                  -->
                <requestedExecutionLevel
                    level="asInvoker"
                    uiAccess="false"
                />   
            </requestedPrivileges>
        </security>
    </trustInfo>
</assembly>

Which for me worked and made it print out Windows 10.0 instead of 6.2
Sources: Manifest File, sysinfoapi.h

LancesLance
  • 160
  • 1
  • 9
  • Thanks for the answer. Our original code looked like your example and we had to change it because of the 8.1 issue. The application currently does not have a manifest so it showed 6.2. – Stanislas Dolcini Nov 04 '21 at 10:49
2

Except the very weak, atleast for me, solution of considering Windows 10 builds greater than 22000, such as Windows 11, the only solution I found which is actually working is the WMIs Win32_OperatingSystem class - Caption property.

On my dev Windows 10 machine it gives the following string: Microsoft Windows 10 Pro.

On my other dev machine, with Windows 11 installed, the same function gives: Microsoft Windows 11 Pro.

The difference is in the string values - "10" vs "11" - but this is at least something far better than the "build greater than" solution.

C# and C++ work well.

ouflak
  • 2,458
  • 10
  • 44
  • 49
Denis B
  • 56
  • 3
  • 1
    This answer is a [duplicate answer](https://stackoverflow.com/questions/68510685/how-to-detect-windows-11-using-delphi-10-3-3/70076935#70076935) to [this question](https://stackoverflow.com/questions/68510685/how-to-detect-windows-11-using-delphi-10-3-3/70076935#70076935). Not necessarily a bad thing, but should be noted, especially as Windows 11 is beginning to appear in the industry. – ouflak Nov 23 '21 at 10:25
-1

I am able to retrieve the version number properly. Copying my code below. Using windows.h should work instead of sysinfoapi.h

#include<windows.h>
#include<stdio.h>
int main() {
     OSVERSIONINFOEX info;
     ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
     info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
     GetVersionEx((LPOSVERSIONINFO)&info);
     printf("Windows version: %u.%u\n", info.dwMajorVersion, info.dwMinorVersion);
}

Alternate way to read version number is to use GetProcAddress. 'GetProcAddress' returns the address of specified DLL function.

#include<iostream>
#include<string>
#include <windows.h>
using namespace std;
void main() {
   int osver= 0.0;
   NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOEXW);
   OSVERSIONINFOEXW osInfo;
   *(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");    
     if (NULL != RtlGetVersion) {
            osInfo.dwOSVersionInfoSize = sizeof(osInfo);
            RtlGetVersion(&osInfo);
            osver = osInfo.dwMajorVersion;
      }
}
so_sc
  • 17
  • 1
  • 7
  • 1
    Note for people finding this in the future, this code will not work on versions of Windows after Windows 10 and later. GetVersion and GetVersionEx simply return build 6.2, which corresponds to the Windows 8 version. Both functions are documented as being deprecated. – jeremyong Jan 19 '23 at 15:12