【问题标题】:How can I detect if my app is running on Windows 10如何检测我的应用程序是否在 Windows 10 上运行
【发布时间】:2015-10-31 08:17:28
【问题描述】:

我正在寻找一种方法来检测我的 C# 应用程序是否在 Windows 10 上运行。

我曾希望 Environment.OSVersion 能解决问题,但这似乎在 Windows 8.1 和 Windows 10 上返回 Version6.3.9600.0

this 等其他解决方案似乎也无法区分 Windows 8 和 Windows 10。

有什么建议吗?


为什么我需要这样做?

因为我使用 WinForms WebBrowser 控件来托管在旧 IE 版本中崩溃和烧毁的 OAuth 页面(我的应用程序连接到 user's Nest account...)。

默认情况下,WebBrowser 控件模拟 IE7。使用注册表项,您可以告诉它模拟安装在主机 PC 上的最新版本的 IE。但是,直到 Windows 8.1(和 Windows 10 的预发行版)的value that worked 在 Windows 10 的最终版本中不起作用。

【问题讨论】:

  • 您是否在 Windows 10 上 manifest the app
  • 您是否使用兼容模式运行程序?
  • 还有其他方式获取此信息,查看此帖stackoverflow.com/questions/6331826/…
  • @Graffito - 我的应用没有在兼容模式下运行。
  • 你试过1200012001FEATURE_BROWSER_EMULATION吗?

标签: c# windows-10


【解决方案1】:

你试过下面吗? [需要添加对Microsoft.VisulaBasicdll的引用]

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

在我的机器上,Microsoft Windows 7 Ultimate

【讨论】:

  • 这在 Windows 10 中已被折旧。
  • @Claies,不知道,但那太糟糕了:)
  • 另外...我宁愿避免向我的 C# 项目添加 VisualBasic 引用。
【解决方案2】:

如果您查看注册表,您会发现环境名称:

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; 添加到您的使用中。

【讨论】:

  • @RichardEverett 公平点!现在的孩子们和他们的“应用程序”,我不知道...... :)
  • 在 Windows 100 上使用 StartsWith 将不正确。
  • @MitatKoyuncu 还不存在。我只是说(主要是开玩笑)这不是未来的证据。他们不得不跳过 Windows 9,因为所有代码都使用StartsWith("Windows 9") 来检测 Windows 95 和 98。
  • ...不,不要这样做。
  • CurrentMajorVersionNumber 中检查实际的 numeric 版本值要安全得多,正如 Spiralis 在他们的回答中所建议的那样。如果该值不存在,那么您可以放心地假设它不是 Win10 ;)
【解决方案3】:

在后台,Environment.OSVersion 使用已被弃用的 GetVersionEx function。该文档警告您观察到的行为:

未针对 Windows 8.1 或 Windows 10 显示的应用程序将返回 Windows 8 操作系统版本值 (6.2)。

文档继续推荐:

识别当前操作系统通常不是确定特定操作系统功能是否存在的最佳方式。这是因为操作系统可能在可再发行的 DLL 中添加了新功能。与其使用 GetVersionEx 来确定操作系统平台或版本号,不如测试该功能本身是否存在。

如果上述建议不适合您的情况,并且您确实想检查实际运行的操作系统版本,那么文档还提供了关于此的提示:

要将当前系统版本与所需版本进行比较,请使用 VerifyVersionInfo 函数而不是使用 GetVersionEx 自行进行比较。

以下文章发布了使用 VerifyVersionInfo 函数的有效解决方案:Version Helper API for .NET

充分感谢那篇文章的作者,以下代码 sn-p 应该提供您正在寻找的行为:

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 上测试过代码。

【讨论】:

  • 来自 MSDN:“在 Windows 10 中,VerifyVersionInfo 函数也已被弃用。虽然您仍然可以调用已弃用的函数,但如果您的应用程序没有专门针对 Windows 8.1 或 Windows 10,您将获得 Windows 8 版本(6.2.0.0)。“
  • 不工作,Win10 仍然返回 6.2! “Windows 10:VerifyVersionInfo 在调用时返回 false....”
【解决方案4】:

回答

使用Environment.OSVersion 并添加一个应用程序清单文件,其中相关supportedOS 元素未注释。

例如在

下添加
<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 的回答,因为它不必要地使用了注册表,并且正如 cmets 中提到的那样,它使用了不可靠的字符串解析。

我也不喜欢@sstan 的回答,因为它使用第三方代码,而且无论如何它都需要应用程序清单。

来自MSDN

Windows 10:VerifyVersionInfo 在被调用时返回 false 没有适用于 Windows 8.1 的兼容性清单的应用程序 或 Windows 10,如果设置了 lp​​VersionInfo 参数,则 指定 Windows 8.1 或 Windows 10,即使当前运行 系统版本为 Windows 8.1 或 Windows 10。具体而言, VerifyVersionInfo 具有以下行为:

• 如果应用程序没有清单,VerifyVersionInfo 的行为就像操作系统版本是 Windows 8 (6.2)。

• 如果应用程序的清单包含与 Windows 8.1 对应的 GUID,则 VerifyVersionInfo 的行为就像操作系统版本是 Windows 8.1 (6.3)。

• 如果应用程序的清单包含对应的 GUID 对于 Windows 10,VerifyVersionInfo 的行为就像操作系统一样 版本是 Windows 10 (10.0)。

原因是因为 VerifyVersionInfo 在 Windows 10 中已弃用。

我已经在 Windows 10 上进行了测试,当 app.Manifest 包含上述相关 GUID 时,Environment.OSVersion 确实可以正常工作。这很可能是他们没有从 .Net Framework 更改或弃用它的原因。

【讨论】:

  • 这是正确的官方方法。我想向其他人指出,在使用您的 app.manifest 进行测试时,请确保它实际上在您的输出文件夹中。在调试配置中,我的没有复制到bin/Debug。在我尝试发布并进一步挖掘之前,我认为app.manifest 不起作用。
  • 为我工作。在我将上述内容添加到 app.manifest 之前,一直显示 NT 6.2 版。
  • 这个问题中唯一缺少的是一个用法示例。
【解决方案5】:

我建议使用注册表来查找您想要的值。微软已经改变了 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;
            }
        }
    }
}

【讨论】:

  • 不错!这为我完成了工作。不过,除了“CurrentMajorVersionNumber”之外,没有费心检查其他任何东西;该应用程序只需要知道它是否在 Win10 上运行。如果注册表项不存在,因为它是旧版本,那么我会说任务完成了。
【解决方案6】:

您不能使用 Version Helper 功能吗? https://msdn.microsoft.com/en-us/library/windows/desktop/dn424972(v=vs.85).aspx

是Windows10或更大

指示当前操作系统版本是否匹配或大于 视窗 10 版本。对于 Windows 10,IsWindows10OrGreater 返回 false 除非应用程序包含一个清单,其中包括 包含指定 Windows 的 GUID 的兼容性部分 10.

并添加 GUID: https://msdn.microsoft.com/en-ca/library/windows/desktop/dn481241(v=vs.85).aspx

【讨论】:

    【解决方案7】:

    试试这个:

    string subKey = @"SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion";
    Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine;
    Microsoft.Win32.RegistryKey skey = key.OpenSubKey(subKey);
    
    string name = skey.GetValue("ProductName").ToString();
    

    然后你可以只使用 if 子句:

    if(name.Contains("Windows 10"))
    {
        //... procedures
    }
    else
    {
       //... procedures
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-01
      • 2011-06-10
      • 2020-01-16
      • 2021-03-10
      相关资源
      最近更新 更多