C#中获取操作系统版本

在系统维护过程中,为了方便分析应用程序错误,我们经常要确定用户的环境,如操作系统的版本。为了快速准确地获取版本信息,可以通过程序读取(有的小白用户可能不知道怎么查看系统版本)。一般获取操作系统版本的方法有三种:

一、环境参数法

通过Environment即可获取Version版本信息。

1
2
OperatingSystem os = Environment.OSVersion;
Version ver = os.Version;

Version版本号分四段,其定义如下:

Major:主版本号;

Minor:次版本号;

Build:内部版本号;

Revision:修订版本号。

版本号对应关系表:

此方法在Win10下获取的值可能不是10,这是因为版本不兼容,解决方案是程序应用清单中增加配置:

1
2
3
4
5
6
7
8
<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}"/>
        </application>
</compatibility>

二、注册表法

通过获取注册存储的信息来获取操作系统版本号信息,位置在:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/// <summary>
/// 操作系统信息
/// </summary>
public static class ComputerInfo
{
    /// <summary>
    /// 操作系统名称
    /// </summary>
    public static string WinProductName
    {
        get
        {
            if (TryGetRegistryKey(@"SOFTWARE\Microsoft\WindowsNT\CurrentVersion", "ProductName", out var productName))
            {
                return (string)productName;
            }
            return "未知";
        }
    }
 
    /// <summary>
    /// 操作系统主要版本号
    /// </summary>
    public static uint WinMajorVersion
    {
        get
        {
            if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", out var major))
            {
                return (uint) major;
            }
 
            if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out var version))
                return 0;
 
            var versionParts = ((string) version).Split('.');
            if (versionParts.Length != 2) return 0;
            return uint.TryParse(versionParts[0], out var majorAsUInt) ? majorAsUInt : 0;
        }
    }
 
    /// <summary>
    /// 操作系统次要版本号
    /// </summary>
    public static uint WinMinorVersion
    {
        get
        {
            if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMinorVersionNumber", out var minor))
            {
                return (uint) minor;
            }
 
            if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out var version))
                return 0;
 
            var versionParts = ((string) version).Split('.');
            if (versionParts.Length != 2) return 0;
            return uint.TryParse(versionParts[1], out var minorAsUInt) ? minorAsUInt : 0;
        }
    }
 
    /// <summary>
    /// 判断是否为Server系统
    /// </summary>
    public static uint IsServer
    {
        get
        {
            if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "InstallationType",
                    out var installationType))
            {
                return (uint) (installationType.Equals("Client") ? 0 : 1);
            }
 
            return 0;
        }
    }
 
    /// <summary>
    /// 获取注册表值
    /// </summary>
    /// <param name="path">路径</param>
    /// <param name="key">键</param>
    /// <param name="value">值</param>
    /// <returns>是否成功</returns>
    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;
        }
    }
}

三、底层API法(推荐)

使用RtlGetVersion或GetVersionEx来实现任何Windows系统版本号的读取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public static class VersionHelper
{
    [SecurityCritical]
    [DllImport("ntdll.dll", SetLastError = true)]
    public static extern bool RtlGetVersion(ref OsVersionInfoEx versionInfo);
 
    [DllImport("kernel32.dll")]
    public static extern bool GetVersionEx([In, Out] OsVersionInfoEx versionInfo);
 
    /// <summary>
    /// 操作系统版本信息结构
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct OsVersionInfoEx
    {
        //定义:https://docs.microsoft.com/zh-cn/windows-hardware/drivers/ddi/wdm/ns-wdm-_osversioninfoexw
        internal int OSVersionInfoSize;     //对象结构的大小
        internal int MajorVersion;          //主要版本号
        internal int MinorVersion;          //次要版本号
        internal int BuildNumber;           //内部版本号
        internal int PlatformId;            //平台标识符
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        internal string CSDVersion;         //补丁版本字符串,如Service Pack 3
        internal ushort ServicePackMajor;   //补丁版本的主要版本号,如Service Pack 3主要版本号为3
        internal ushort ServicePackMinor;   //补丁版本的次要版本号,如Service Pack 3次要版本号为0
        internal short SuiteMask;           //可用的产品套件,如VER_SUITE_SINGLEUSERTS表示支持远程桌面
        internal byte ProductType;          //产品类型,如VER_NT_WORKSTATION表示Windows 2000 或更高版本专业版
        internal byte Reserved;             //保留供将来使用
    }
 
    public static Version GetVersion()
    {
        var osVersionInfo = new OsVersionInfoEx { OSVersionInfoSize = Marshal.SizeOf(typeof(OsVersionInfoEx)) };
        if (!RtlGetVersion(ref osVersionInfo))
        {
            osVersionInfo = new OsVersionInfoEx
            {
                OSVersionInfoSize = Marshal.SizeOf(typeof(OsVersionInfoEx))
            };
            GetVersionEx(osVersionInfo);
        }
 
        var version = new Version(
            osVersionInfo.MajorVersion,
            osVersionInfo.MinorVersion,
            osVersionInfo.BuildNumber);
 
        return version;
    }
}
posted @   我也是个傻瓜  阅读(4972)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2016-03-26 .NET破解之迅捷PDF转换器(续)
点击右上角即可分享
微信分享提示