Получение версии ОС Windows программно

Я пытаюсь получить версию Windows с C# на моем компьютере с Windows 10.

Я всегда получаю эти значения (с C# \ C++):

Major: 6

Незначительное: 2

Какая ОС Windows 8, соответственно MSDN

Код C#:

var major = OperatingSystem.Version.Major
var minor  = OperatingSystem.Version.Minor

Код C++

void print_os_info()
{
    //http://stackru.com/questions/1963992/check-windows-version
    OSVERSIONINFOW info;
    ZeroMemory(&info, sizeof(OSVERSIONINFOW));
    info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);

    LPOSVERSIONINFOW lp_info = &info;
    GetVersionEx(lp_info);

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

Windows 10 предположительно будет с такими:

Major: 10

Незначительный: 0 *

  • (Когда я беру файл дампа из запущенного процесса, я вижу, что версия ОС этого файла установлена ​​на 10.0)

построено: 10.0.10586.0 (th2_release.151029-1700)

Что мне здесь не хватает?

6 ответов

Решение

Поскольку принятый ответ только для C#, вот решение для C++.

Он использует RtlGetVersion в ntdll.dll, который использует ту же структуру, что и GetVersionEx (имя отличается, но элементы совпадают) и дает правильную версию. Поскольку эта функция обычно используется для разработки драйверов, функция объявляется в DDK, а не в SDK. Поэтому я использовал динамическое решение для вызова функции. Помните, что ntdll.dll загружается и освобождается при каждом вызове. Так что если вам нужна функция чаще, держите библиотеку загруженной.

Структура, на которую указывает pOSversion, должна быть инициализирована, как для GetVersionEx.

BOOL GetTrueWindowsVersion(OSVERSIONINFOEX* pOSversion)
{
   // Function pointer to driver function
   NTSTATUS (WINAPI *pRtlGetVersion)(
      PRTL_OSVERSIONINFOW lpVersionInformation) = NULL;

   // load the System-DLL
   HINSTANCE hNTdllDll = LoadLibrary("ntdll.dll");

   // successfully loaded?
   if (hNTdllDll != NULL)
   {
      // get the function pointer to RtlGetVersion
      pRtlGetVersion = (NTSTATUS (WINAPI *)(PRTL_OSVERSIONINFOW))
            GetProcAddress (hNTdllDll, "RtlGetVersion");

      // if successfull then read the function
      if (pRtlGetVersion != NULL)
         pRtlGetVersion((PRTL_OSVERSIONINFOW)pOSversion);

      // free the library
      FreeLibrary(hNTdllDll);
   } // if (hNTdllDll != NULL)

   // if function failed, use fallback to old version
   if (pRtlGetVersion == NULL)
      GetVersionEx((OSVERSIONINFO*)pOSversion);

   // always true ...
   return (TRUE);
} // GetTrueWindowsVersion

В моем сценарии мне нужно было мое приложение для сбора информации о компьютере для возможных отчетов об ошибках и статистики.

Я не нашел решений, в которых манифест приложения должен был быть добавлен удовлетворительно. К сожалению, большинство предложений, которые я нашел во время поиска в Google, это именно так.

Дело в том, что при использовании манифеста каждая версия ОС должна быть добавлена ​​в него вручную, чтобы эта конкретная версия ОС могла сообщать о себе во время выполнения.

Другими словами, это становится условием гонки: пользователь моего приложения вполне может использовать версию моего приложения, которая предшествует используемой ОС. Мне бы пришлось обновить приложение сразу же, когда Microsoft выпустит новую версию ОС. Мне также пришлось бы заставлять пользователей обновлять приложение одновременно с обновлением ОС.

Другими словами, не очень выполнимо.

После просмотра параметров я нашел несколько ссылок (на удивление, по сравнению с манифестом приложения), которые вместо этого предлагали использовать поиск в реестре.

Мой (рубленый) ComputerInfo класс только WinMajorVersion, WinMinorVersion а также IsServer свойства выглядят так:

using Microsoft.Win32;

namespace Inspection
{
    /// <summary>
    /// Static class that adds convenient methods for getting information on the running computers basic hardware and os setup.
    /// </summary>
    public static class ComputerInfo
    {
        /// <summary>
        ///     Returns the Windows major version number for this computer.
        /// </summary>
        public static uint WinMajorVersion
        {
            get
            {
                dynamic major;
                // The 'CurrentMajorVersionNumber' string value in the CurrentVersion key is new for Windows 10, 
                // and will most likely (hopefully) be there for some time before MS decides to change this - again...
                if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", out major))
                {
                    return (uint) major;
                }

                // When the 'CurrentMajorVersionNumber' value is not present we fallback to reading the previous key used for this: 'CurrentVersion'
                dynamic version;
                if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out version))
                    return 0;

                var versionParts = ((string) version).Split('.');
                if (versionParts.Length != 2) return 0;
                uint majorAsUInt;
                return uint.TryParse(versionParts[0], out majorAsUInt) ? majorAsUInt : 0;
            }
        }

        /// <summary>
        ///     Returns the Windows minor version number for this computer.
        /// </summary>
        public static uint WinMinorVersion
        {
            get
            {
                dynamic minor;
                // The 'CurrentMinorVersionNumber' string value in the CurrentVersion key is new for Windows 10, 
                // and will most likely (hopefully) be there for some time before MS decides to change this - again...
                if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMinorVersionNumber",
                    out minor))
                {
                    return (uint) minor;
                }

                // When the 'CurrentMinorVersionNumber' value is not present we fallback to reading the previous key used for this: 'CurrentVersion'
                dynamic version;
                if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out version))
                    return 0;

                var versionParts = ((string) version).Split('.');
                if (versionParts.Length != 2) return 0;
                uint minorAsUInt;
                return uint.TryParse(versionParts[1], out minorAsUInt) ? minorAsUInt : 0;
            }
        }

        /// <summary>
        ///     Returns whether or not the current computer is a server or not.
        /// </summary>
        public static uint IsServer
        {
            get
            {
                dynamic installationType;
                if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "InstallationType",
                    out installationType))
                {
                    return (uint) (installationType.Equals("Client") ? 0 : 1);
                }

                return 0;
            }
        }

        private static bool TryGetRegistryKey(string path, string key, out dynamic value)
        {
            value = null;
            try
            {
                using(var rk = Registry.LocalMachine.OpenSubKey(path))
                {
                    if (rk == null) return false;
                    value = rk.GetValue(key);
                    return value != null;
                }
            }
            catch
            {
                return false;
            }
        }
    }
}
Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentBuildNumber", string.Empty).ToString()

один и тот же код для всех ОС от XP до текущей 10.16299, в Windows 8 сценарии не работают должным образом

Свойство OSVersion сообщает об одном и том же номере версии (6.2.0.0) для Windows 8 и Windows 8.1 и об одном и том же номере основной и вспомогательной версии для Windows 10.

https://msdn.microsoft.com/library/system.environment.osversion.aspx

Вам нужно будет добавить app.manifest к вашему заявлению:

введите описание изображения здесь

введите описание изображения здесь

затем раскомментируйте следующую строку:

<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />

Вы можете сделать это в C# так же, как в C++

[SecurityCritical]
[DllImport("ntdll.dll", SetLastError = true)]
internal static extern bool RtlGetVersion(ref OSVERSIONINFOEX versionInfo);
[StructLayout(LayoutKind.Sequential)]
internal struct OSVERSIONINFOEX
{
    // The OSVersionInfoSize field must be set to Marshal.SizeOf(typeof(OSVERSIONINFOEX))
    internal int OSVersionInfoSize;
    internal int MajorVersion;
    internal int MinorVersion;
    internal int BuildNumber;
    internal int PlatformId;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
    internal string CSDVersion;
    internal ushort ServicePackMajor;
    internal ushort ServicePackMinor;
    internal short SuiteMask;
    internal byte ProductType;
    internal byte Reserved;
}

...

var osVersionInfo = new OSVERSIONINFOEX { OSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFOEX)) };
if (!RtlGetVersion(ref osVersionInfo))
{
  // TODO: Error handling, call GetVersionEx, etc.
}

Вы можете читать из реестра через код и делать конкретные действия, которые вы хотели.

Скажи для бывших:

Ключ реестра вы можете найти здесь:

HKEY_LOCAL_MACHINE \ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ \Microsoft\Windows NT\CurrentVersion, а затем найдите "ProductName"

Вы можете открыть информацию реестра, запустив regedit.exe (windows+r)

var reg              =Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\WindowsNT\CurrentVersion");

        string productName = (string)reg.GetValue("ProductName");

        if (productName.StartsWith("Windows 10"))
        {
        }
        else
        {
        }
Другие вопросы по тегам