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

后端 未结 7 1342
清酒与你
清酒与你 2020-12-09 01:17

I\'m looking for a means to detect if my C# app is running on Windows 10.

I had hoped that Environment.OSVersion would do the trick, but this seems to r

相关标签:
7条回答
  • 2020-12-09 01:43

    Under the hood, Environment.OSVersion uses the GetVersionEx function, which has been deprecated. 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).

    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. Rather than using GetVersionEx to determine the operating system platform or version number, test for the presence of the feature itself.

    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.

    The following article has posted a working solution using the VerifyVersionInfo function: 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.

    0 讨论(0)
  • 2020-12-09 01:47

    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.

    Here is the code I uses, that correctly identifies Windows 10 as well:

    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;
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-09 01:52

    Can't you use the Version Helper functions? https://msdn.microsoft.com/en-us/library/windows/desktop/dn424972(v=vs.85).aspx

    IsWindows10OrGreater

    Indicates if the current OS version matches, or is greater than, the Windows 10 version. 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.

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

    0 讨论(0)
  • 2020-12-09 01:55

    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(name.Contains("Windows 10"))
    {
        //... procedures
    }
    else
    {
       //... procedures
    }
    
    0 讨论(0)
  • 2020-12-09 01:56

    Answer

    Use Environment.OSVersion and add an application manifest file with relevant supportedOS elements uncommented.

    e.g. add this under <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.

    I also don't like the answer from @sstan because it uses third party code and it needs the application manifest anyway.

    From 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:

    • If the application has no manifest, VerifyVersionInfo behaves as if the operation system version is 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).

    • 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).

    The reason is because VerifyVersionInfo is deprecated in Windows 10.

    I have tested on Windows 10 and indeed Environment.OSVersion works exactly as expected when the app.Manifest contains the relevant GUID as above. That is most likely why they did not change or deprecate it from .Net Framework.

    0 讨论(0)
  • 2020-12-09 01:58

    Have you tried below? [You need to add a reference to Microsoft.VisulaBasic dll]

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

    On my machine it gives, Microsoft Windows 7 Ultimate

    0 讨论(0)
提交回复
热议问题