Определение версии Windows через RtlGetVersion

Board index Программирование .NET

Description: Программирование с использованием платформы Microsoft.NET

#1by mexan » 11.05.2025, 21:59

Столкнулся с тем, что Environment.OSVersion в C# может возвращать некорректную информацию о версии Windows, особенно начиная с Windows 10 — например, всегда показывает 6.2 (Windows 8), если отсутствует манифест или нет специальных настроек.

Чтобы обойти это ограничение, использовал прямой вызов нативной WinAPI-функции RtlGetVersion из ntdll.dll, которая возвращает реальную версию системы, независимо от манифеста и политики совместимости.
Code: Select all
using System.Runtime.InteropServices;

namespace WindowsVersionDetector
{
    class Program
    {
        static void Main(string[] args)
        {
            string version = GetAccurateWindowsVersion();
            Console.WriteLine($"Текущая версия Windows: {version}");
            Console.ReadLine();
        }

        private static string GetAccurateWindowsVersion()
        {
            OSVERSIONINFOEX versionInfo = new()
            {
                dwOSVersionInfoSize = Marshal.SizeOf<OSVERSIONINFOEX>()
            };

            int result = RtlGetVersion(ref versionInfo);

            if (result != 0)
                return "Unknown";

            int major = versionInfo.dwMajorVersion;
            int minor = versionInfo.dwMinorVersion;
            int build = versionInfo.dwBuildNumber;

            if (major == 10 && build >= 22000)
                return "Windows 11";
            else if (major == 10)
                return "Windows 10";
            else if (major == 6 && minor == 3)
                return "Windows 8.1";
            else if (major == 6 && minor == 2)
                return "Windows 8";
            else if (major == 6 && minor == 1)
                return "Windows 7";
            else if (major == 6 && minor == 0)
                return "Windows Vista";
            else if (major == 5 && minor == 1)
                return "Windows XP";
            else
                return $"Unknown ({major}.{minor}.{build})";
        }

        [DllImport("ntdll.dll", SetLastError = true)]
        private static extern int RtlGetVersion(ref OSVERSIONINFOEX versionInfo);

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        private struct OSVERSIONINFOEX
        {
            public int dwOSVersionInfoSize;
            public int dwMajorVersion;
            public int dwMinorVersion;
            public int dwBuildNumber;
            public int dwPlatformId;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string szCSDVersion;

            public ushort wServicePackMajor;
            public ushort wServicePackMinor;
            public ushort wSuiteMask;
            public byte wProductType;
            public byte wReserved;
        }
    }
}
Image
mexan
Администратор
Reputation: 0
Posts: 167
Topics: 129

Return to .NET