Подтвердить что ты не робот

Как определить, работает ли мое приложение в Windows 10

Я ищу способ определить, работает ли мое приложение С# в Windows 10.

Я надеялся, что Environment.OSVersion выполнит трюк, но, похоже, он возвращает Version из 6.3.9600.0 в Windows 8.1 и Windows 10.

Другие решения, такие как это, похоже, не отличаются между Windows 8 и Windows 10.

Любые предложения?


Зачем мне это нужно?

Поскольку я использую элемент управления WinForms WebBrowser для размещения страницы OAuth, которая сбой и ожоги в старых версиях IE (мое приложение подключается к учетной записи пользователя Nest...).

По умолчанию элемент управления WebBrowser эмулирует IE7. Используя ключ реестра, вы можете сказать, что он эмулирует последнюю версию IE, установленную на главном ПК. Однако значение которое работало до Windows 8.1 (и предварительные выпуски Windows 10), не работает в окончательной версии Windows 10.

4b9b3361

Ответ 1

Если вы посмотрите на реестр, вы найдете имя среды:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName

Например, мое имя продукта Windows 10 Home:

Реестр

С помощью этого кода вы получите, если это Windows 10:

 static bool IsWindows10()
 {
     var reg = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion");

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

     return productName.StartsWith("Windows 10");
 }

Примечание. Добавьте using Microsoft.Win32; к вашим услугам.

Ответ 2

Ответ

Используйте Environment.OSVersion и добавьте файл манифеста приложения с соответствующими supportedOS элементами без комментирования.

например. добавьте это под < asmv1: assembly >

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
    <application> 
        <!-- Windows 10 --> 
        <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
        <!-- Windows 8.1 -->
        <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
        <!-- Windows Vista -->
        <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> 
        <!-- Windows 7 -->
        <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
        <!-- Windows 8 -->
        <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
    </application> 
</compatibility>

Причина

Мне не нравится ответ от @Mitat Koyuncu, потому что он без необходимости использует реестр и, как упоминалось в комментариях, использует ненадежный синтаксический анализ строк.

Мне также не нравится ответ от @sstan, потому что он использует сторонний код, и ему все равно нужен манифест приложения.

От MSDN:

Windows 10: VerifyVersionInfo возвращает false при вызове  приложения, которые не имеют манифест совместимости для Windows 8.1  или Windows 10, если параметр lpVersionInfo установлен так, чтобы он  указывает Windows 8.1 или Windows 10, даже если текущая операционная  системная версия - Windows 8.1 или Windows 10. В частности,   VerifyVersionInfo имеет следующее поведение:

• Если приложение не имеет манифеста, VerifyVersionInfo ведет себя так, как если бы операционная система была версией Windows 8 (6.2).

• Если приложение имеет манифест, содержащий GUID, соответствующий Windows 8.1, VerifyVersionInfo ведет себя так, как если бы операционная система была версией Windows 8.1 (6.3).

• Если приложение имеет манифест, содержащий идентификатор GUID, который соответствует к Windows 10, VerifyVersionInfo ведет себя так, как если бы операционная система версия Windows 10 (10.0).

Причина в том, что VerifyVersionInfo устарела в Windows 10.

Я тестировал в Windows 10 и действительно Environment.OSVersion работает точно так, как ожидалось, когда app.Manifest содержит соответствующий идентификатор GUID, как указано выше. Скорее всего, они не изменили или не отказались от него .Net Framework.

Ответ 3

Под капотом Environment.OSVersion используется функция GetVersionEx, который устарел. Документация предупреждает о поведении, которое вы наблюдаете:

Приложения, не отображаемые для Windows 8.1 или Windows 10, вернут значение версии ОС Windows 8 (6.2).

В документации далее рекомендуется:

Идентификация текущей операционной системы обычно не является лучшим способом определить, присутствует ли конкретная операционная система. Это связано с тем, что операционная система, возможно, добавила новые функции в распространяемую DLL. Вместо использования GetVersionEx для определения платформы или номера версии операционной системы проверьте наличие самой функции.

Если приведенная выше рекомендация не подходит для вашего случая, и вы действительно хотите проверить фактическую версию операционной системы, тогда в документации также будет намек на это:

Чтобы сравнить текущую версию системы с требуемой версией, используйте VerifyVersionInfo вместо использования GetVersionEx, чтобы выполнить сравнение самостоятельно.

В следующей статье опубликовано рабочее решение с использованием функции VerifyVersionInfo: API Версии API для .NET.

Предоставляя полную защиту автору этой статьи, следующий фрагмент кода должен предоставить поведение, которое вы ищете:

public class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(IsWindowsVersionOrGreater(6, 3, 0)); // Plug in appropriate values.
    }

    [StructLayout(LayoutKind.Sequential)]
    struct OsVersionInfoEx
    {
        public uint OSVersionInfoSize;
        public uint MajorVersion;
        public uint MinorVersion;
        public uint BuildNumber;
        public uint PlatformId;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string CSDVersion;
        public ushort ServicePackMajor;
        public ushort ServicePackMinor;
        public ushort SuiteMask;
        public byte ProductType;
        public byte Reserved;
    }

    [DllImport("kernel32.dll")]
    static extern ulong VerSetConditionMask(ulong dwlConditionMask,
       uint dwTypeBitMask, byte dwConditionMask);
    [DllImport("kernel32.dll")]
    static extern bool VerifyVersionInfo(
        [In] ref OsVersionInfoEx lpVersionInfo,
        uint dwTypeMask, ulong dwlConditionMask);

    static bool IsWindowsVersionOrGreater(
        uint majorVersion, uint minorVersion, ushort servicePackMajor)
    {
        OsVersionInfoEx osvi = new OsVersionInfoEx();
        osvi.OSVersionInfoSize = (uint)Marshal.SizeOf(osvi);
        osvi.MajorVersion = majorVersion;
        osvi.MinorVersion = minorVersion;
        osvi.ServicePackMajor = servicePackMajor;
        // These constants initialized with corresponding definitions in
        // winnt.h (part of Windows SDK)
        const uint VER_MINORVERSION = 0x0000001;
        const uint VER_MAJORVERSION = 0x0000002;
        const uint VER_SERVICEPACKMAJOR = 0x0000020;
        const byte VER_GREATER_EQUAL = 3;
        ulong versionOrGreaterMask = VerSetConditionMask(
            VerSetConditionMask(
                VerSetConditionMask(
                    0, VER_MAJORVERSION, VER_GREATER_EQUAL),
                VER_MINORVERSION, VER_GREATER_EQUAL),
            VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
        uint versionOrGreaterTypeMask = VER_MAJORVERSION |
            VER_MINORVERSION | VER_SERVICEPACKMAJOR;
        return VerifyVersionInfo(ref osvi, versionOrGreaterTypeMask,
            versionOrGreaterMask);
    }
}

Отказ от ответственности: у меня пока нет Windows 10, поэтому я не тестировал код в Windows 10.

Ответ 4

Я предлагаю использовать реестр, чтобы найти нужные значения. Microsoft изменила способ, которым Windows 10 указана в реестре, поэтому код должен адаптироваться для этого.

Вот код, который я использую, который правильно идентифицирует Windows 10:

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
            {
                var rk = Registry.LocalMachine.OpenSubKey(path);
                if (rk == null) return false;
                value = rk.GetValue(key);
                return value != null;
            }
            catch
            {
                return false;
            }
        }
    }
}

Ответ 5

Вы пробовали внизу? [Вам нужно добавить ссылку на Microsoft.VisulaBasic dll]

new Microsoft.VisualBasic.Devices.ComputerInfo().OSFullName

На моей машине это дает, Microsoft Windows 7 Ultimate