简体   繁体   English

如何检测我的应用程序是否在Windows 10上运行

[英]How can I detect if my app is running on Windows 10

I'm looking for a means to detect if my C# app is running on Windows 10. 我正在寻找一种方法来检测我的C#应用​​程序是否在Windows 10上运行。

I had hoped that Environment.OSVersion would do the trick, but this seems to return a Version of 6.3.9600.0 on Windows 8.1 and Windows 10. 我曾希望Environment.OSVersion可以做到这一点,但这似乎在Windows 8.1和Windows 10上返回了6.3.9600.0 Version

Other solutions such as this don't seem to distinguish between Windows 8 and Windows 10 either. 如其他解决方案, 似乎并没有的Windows 8和Windows 10之间进行区分两种。

Any suggestions? 有什么建议?


Why do I need to do this? 为什么我需要这样做?

Because I'm using a WinForms WebBrowser control to host an OAuth page that crashes and burns in older IE versions (my app connects to a user's Nest account ...). 因为我使用WinForms WebBrowser控件来托管OAuth页面,该页面在旧的IE版本中崩溃并烧毁(我的应用程序连接到用户的Nest帐户 ......)。

By default, the WebBrowser control emulates IE7. 默认情况下,WebBrowser控件模拟IE7。 Using a Registry key, you can tell it to emulate the latest version of IE that is installed on the host PC. 使用注册表项,您可以告诉它模拟主机PC上安装的最新版本的IE。 However, the value that worked up to Windows 8.1 (and pre-releases of Windows 10) does not work in the final version of Windows 10. 然而, 该工作值高达8.1的Windows(和Windows 10的预发行版)无法在Windows 10的最终版本。

Answer 回答

Use Environment.OSVersion and add an application manifest file with relevant supportedOS elements uncommented. 使用Environment.OSVersion并添加一个应用程序清单文件,其中包含未注释的相关supportedOS元素。

eg add this under <asmv1:assembly> 例如,在<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>

Reason 原因

I don't like the answer from @Mitat Koyuncu because is uses the registry unnecessarily and as mentioned in the comments uses unreliable string parsing. 我不喜欢@Mitat Koyuncu的答案,因为它不必要地使用注册表,并且在评论中提到使用不可靠的字符串解析。

I also don't like the answer from @sstan because it uses third party code and it needs the application manifest anyway. 我也不喜欢@sstan的答案,因为它使用第三方代码,无论如何它都需要应用程序清单。

From MSDN : 来自MSDN

Windows 10: VerifyVersionInfo returns false when called by applications that do not have a compatibility manifest for Windows 8.1 or Windows 10 if the lpVersionInfo parameter is set so that it specifies Windows 8.1 or Windows 10, even when the current operating system version is Windows 8.1 or Windows 10. Specifically, VerifyVersionInfo has the following behavior: Windows 10:如果设置了lpVersionInfo参数以便指定Windows 8.1或Windows 10,即使当前操作系统版本为Windows 8.1或者Windows 10,则在没有Windows 8.1或Windows 10兼容性清单的应用程序调用时, VerifyVersionInfo将返回false Windows 10.具体来说, VerifyVersionInfo具有以下行为:

• If the application has no manifest, VerifyVersionInfo behaves as if the operation system version is Windows 8 (6.2). •如果应用程序没有清单,则VerifyVersionInfo的行为就像操作系统版本是Windows 8(6.2)一样。

• If the application has a manifest that contains the GUID that corresponds to Windows 8.1, VerifyVersionInfo behaves as if the operation system version is Windows 8.1 (6.3). •如果应用程序的清单包含与Windows 8.1对应的GUID,则VerifyVersionInfo的行为就像操作系统版本是Windows 8.1(6.3)一样。

• If the application has a manifest that contains the GUID that corresponds to Windows 10, VerifyVersionInfo behaves as if the operation system version is Windows 10 (10.0). •如果应用程序的清单包含与Windows 10对应的GUID,则VerifyVersionInfo的行为就像操作系统版本是Windows 10(10.0)一样。

The reason is because VerifyVersionInfo is deprecated in Windows 10. 原因是因为Windows 10中不推荐使用VerifyVersionInfo。

I have tested on Windows 10 and indeed Environment.OSVersion works exactly as expected when the app.Manifest contains the relevant GUID as above. 我已经在Windows 10上进行了测试,当app.Manifest包含上面的相关GUID时, Environment.OSVersion确实与预期完全一样。 That is most likely why they did not change or deprecate it from .Net Framework. 这很可能是因为他们没有从.Net Framework更改或弃用它。

If you look at registry you will found environment name: 如果你看一下注册表,你会发现环境名称:

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

For example my product name is Windows 10 Home : 例如,我的产品名称是Windows 10 Home

注册处

With this code you get if it Windows 10: 使用此代码,如果它是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");
 }

Note: Add using Microsoft.Win32; 注意: using Microsoft.Win32;添加using Microsoft.Win32; to your usings. 对你的使用。

Under the hood, Environment.OSVersion uses the GetVersionEx function , which has been deprecated. 在引擎盖下, Environment.OSVersion使用GetVersionEx函数 ,该函数已被弃用。 The documentation warns about the behavior you observed: 文档警告您观察到的行为:

Applications not manifested for Windows 8.1 or Windows 10 will return the Windows 8 OS version value (6.2). 未在Windows 8.1或Windows 10中显示的应用程序将返回Windows 8 OS版本值(6.2)。

The documentation goes on to recommend: 文档接着建议:

Identifying the current operating system is usually not the best way to determine whether a particular operating system feature is present. 识别当前操作系统通常不是确定特定操作系统功能是否存在的最佳方法。 This is because the operating system may have had new features added in a redistributable DLL. 这是因为操作系统可能在可再发行的DLL中添加了新功能。 Rather than using GetVersionEx to determine the operating system platform or version number, test for the presence of the feature itself. 而不是使用GetVersionEx来确定操作系统平台或版本号,而是测试功能本身的存在。

If the above recommendation is not appropriate for your case, and you really want to check the actual running OS version, then the documentation also provides a hint about this: 如果上述建议不适合您的情况,并且您确实想要检查实际运行的操作系统版本,那么文档还提供了有关此内容的提示:

To compare the current system version to a required version, use the VerifyVersionInfo function instead of using GetVersionEx to perform the comparison yourself. 要将当前系统版本与所需版本进行比较,请使用VerifyVersionInfo函数,而不是使用GetVersionEx 自行执行比较。

The following article has posted a working solution using the VerifyVersionInfo function: Version Helper API for .NET . 以下文章使用VerifyVersionInfo函数发布了一个有效的工作解决方案: Version Helper API for .NET

Giving full credit to the author of that article, the following code snippet should provide the behavior you are looking for: 以下代码段应充分归功于该文章的作者,应该提供您正在寻找的行为:

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

Disclaimer: I don't have Windows 10 yet, so I haven't tested the code on Windows 10. 免责声明:我还没有Windows 10,所以我没有在Windows 10上测试过代码。

I suggest using the registry to find the values you want. 我建议使用注册表来查找所需的值。 Microsoft has changed the way Windows 10 is listed in the registry so the code needs to adapt for that. Microsoft已经改变了Windows 10在注册表中列出的方式,因此代码需要适应它。

Here is the code I uses, that correctly identifies Windows 10 as well: 这是我使用的代码,它也正确识别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;
            }
        }
    }
}

Can't you use the Version Helper functions? 你不能使用版本助手功能吗? https://msdn.microsoft.com/en-us/library/windows/desktop/dn424972(v=vs.85).aspx https://msdn.microsoft.com/en-us/library/windows/desktop/dn424972(v=vs.85).aspx

IsWindows10OrGreater IsWindows10OrGreater

Indicates if the current OS version matches, or is greater than, the Windows 10 version. 指示当前操作系统版本是否与Windows 10版本匹配或大于Windows 10版本。 For Windows 10, IsWindows10OrGreater returns false unless the application contains a manifest that includes a compatibility section that contains the GUID that designates Windows 10. 对于Windows 10,除非应用程序包含包含兼容性部分的清单,否则IsWindows10OrGreater将返回false,该兼容性部分包含指定Windows 10的GUID。

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

Try this one: 试试这个:

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();

and then you can just use an if clause: 然后你可以使用if子句:

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

Have you tried below? 你试过下面的吗? [You need to add a reference to Microsoft.VisulaBasic dll] [您需要添加对Microsoft.VisulaBasic dll的引用]

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

On my machine it gives, Microsoft Windows 7 Ultimate 在我的机器上,它提供, Microsoft Windows 7旗舰版

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我们如何在Windows Phone 8.1应用中检测Windows 10? - How can we detect Windows 10 in Windows Phone 8.1 app? 如何检测连接到运行Windows 10 IoT核心版的Raspberry Pi的USB上的文件? (C#UWP) - How can I detect a file on a USB connected to a Raspberry Pi running Windows 10 IoT Core? (C# UWP) 如何确定我的安装程序是否在 Windows 10 教育版上运行? - How can I determine whether my installer is running on the Education edition of Windows 10? 如何在我的Windows Phone 8应用程序中本地检测时间作弊? - How can I locally detect time cheat in my windows phone 8 app? 如何浏览Windows 10应用程序中的相邻文件? - How can I browse through the neighboring files in my Windows 10 App? 如何检测正在运行的 Windows 版本? - How can I detect which version of Windows is running? 如何检测我的程序是否在Windows中运行? - How to detect if my program is running in Windows? 如何在Windows窗体应用程序中检测Windows 10何时进入平板电脑模式? - How can I detect when Windows 10 enters tablet mode in a Windows Forms application? 如何在Windows应用商店应用中检测设备区域设置? - How can I detect the device culture settings in a Windows Store App? 如何检测何时可以安全升级Windows服务? - How can I detect when it is safe to upgrade my windows service?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM