Environment.TickCount64返回系统启动至今毫秒数,轻量跨平台但休眠时暂停计数;WMI方式通过Win32_OperatingSystem.LastBootUpTime获取真实启动时间,需管理员权限且依赖WMI服务;GetTickCount64 P/Invoke更底层但仅限Windows。

用 Environment.TickCount64 获取开机时长(毫秒级,简单但有坑)
这是最轻量、无需权限、跨 .NET Core/.NET 5+ 的方式,返回系统启动至今的毫秒数。但它本质是“自进程启动后经过的毫秒”,不是绝对开机时间——如果系统运行超 24.8 天,TickCount 会溢出回绕(TickCount64 已解决此问题,但旧代码若误用 TickCount 就会错)。
- 只适用于本机进程运行期间的相对时长估算,不能反推精确启动时间点
-
Environment.TickCount64是 64 位有符号整数,理论支持约 292 年,实际无溢出风险 - 注意:它不等于「系统 uptime」,比如休眠期间该计数器会暂停(Windows 默认行为),所以结果偏小
- 示例:
long upMs = Environment.TickCount64; // 如 1234567890 毫秒 ≈ 14.3 天
用 ManagementObjectSearcher 查询 Win32_OperatingSystem(需引用 System.Management)
这是获取真实系统启动时间点的主流做法,能拿到 LastBootUpTime(WMI 格式字符串),再转成 DateTime。但它依赖 WMI 服务、需要管理员权限(部分环境会拒绝访问)、在容器或精简系统中可能不可用。
- 必须添加 NuGet 包
System.Management(.NET Core 3.1+ 起需单独引用) -
LastBootUpTime是形如"20240512102345.000000+480"的 CIM datetime 字符串,需手动解析 - 常见错误:直接用
Convert.ToDateTime()会抛FormatException;正确做法是用ManagementDateTimeConverter.ToDateTime() - 示例:
var searcher = new ManagementObjectSearcher("SELECT LastBootUpTime FROM Win32_OperatingSystem");<br>foreach (ManagementObject obj in searcher.Get()) {<br> string wmiTime = obj["LastBootUpTime"]?.ToString();<br> DateTime bootTime = ManagementDateTimeConverter.ToDateTime(wmiTime);<br> TimeSpan upTime = DateTime.Now - bootTime;<br>}
用 GetTickCount64 P/Invoke(更底层,但要小心平台兼容性)
这是 Windows 原生 API,和 Environment.TickCount64 底层一致,但你能自己控制调用时机、避免 .NET 运行时初始化延迟影响。不过它只在 Windows 上有效,Linux/macOS 下会报 DllNotFoundException。
- 需声明
[DllImport("kernel32.dll")] public static extern ulong GetTickCount64(); - 返回值是
ulong,比Environment.TickCount64(long)多一位,但实际意义相同 - 关键区别:它不受 .NET 进程启动时机影响,只要系统没重启,每次调用都反映真实内核 uptime
- 仍受休眠影响(Windows 内核计数器在睡眠时暂停)
- 别用
GetTickCount(32 位),它每 ~49.7 天就回绕一次,极易出错
为什么不用 PerformanceCounter?
有人试过用 PerformanceCounter("System", "System Up Time"),理论上可行,但实际踩坑极多:首次实例化慢(WMI 初始化开销)、需要 Performance Logs & Alerts 权限、在某些组策略锁定的域环境中默认禁用、.NET 6+ 在非 Windows 平台会直接 throw PlatformNotSupportedException。
- 该计数器值本质也是从
Win32_OperatingSystem.LastBootUpTime计算而来,多一层封装无必要 - 错误现象典型:
InvalidOperationException: Counter is not supported on this platform或卡在构造函数 - 除非你已经在用大量性能计数器且确认环境可控,否则绕开它更省心
真正麻烦的是休眠——所有基于内核 tick 的方法都会把休眠时间算作“停机”,而用户问的“开机运行时长”往往指“通电持续时间”。这种需求只能靠硬件日志或事件查看器解析 System 日志里 ID=12 的 Kernel-General 事件,那已经超出单行代码范畴了。










