简体   繁体   中英

Detecting Windows 11 properly

I'm a developper from the FOSS game 0 AD ( 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!

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

Except the very weak, as for me, solution of considering Windows 10 build greater than 22000 as Windows 11, the only solution i found, which is actually working, is

The WMIs Win32_OperatingSystem class - Caption property.

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

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

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

C# and C++ - works well.

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;
      }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM