[.Net]windows获取开机时间和计时方法

.net中除了使用Stopwatch计时,还可以使用一些windows API实现计时功能。下面是相关的windows API:

 1         /// <summary> 检索自系统启动以来经过的毫秒数,最多49.7天。 </summary>
 2         /// <returns>返回值是自系统启动以来经过的毫秒数。DWORD </returns>
 3         /// <remarks>GetTickCount功能限于系统定时器,这是通常在10毫秒到16毫秒的范围内的分辨率。
 4         /// GetTickCount函数的分辨率不受GetSystemTimeAdjustment函数所做的调整的影响 。</remarks>
 5         [DllImport("kernel32")]
 6         public static extern uint GetTickCount();
 7 
 8         /// <summary> 检索自系统启动以来经过的毫秒数。 </summary>
 9         /// <returns>毫秒数。ULONGLONG </returns>
10         /// <remarks>GetTickCount64功能限于系统定时器,这是通常在10毫秒到16毫秒的范围内的分辨率。
11         /// GetTickCount64函数的分辨率不受GetSystemTimeAdjustment函数所做的调整的影响 。</remarks>
12         [DllImport("kernel32")]
13         public static extern ulong GetTickCount64();
14 
15         /// <summary> 检索系统时间,以毫秒为单位。系统时间是自Windows启动以来经过的时间。 </summary>
16         /// <returns>返回系统时间(以毫秒为单位)。DWORD</returns>
17         /// <remarks>请注意,timeGetTime函数返回的值是DWORD值。该返回值每2 ^ 32毫秒回绕到0,大约49.71天。这会在直接在计算中使用timeGetTime返回值的代码中引起问题,
18         /// 尤其是在该值用于控制代码执行的情况下。您应该始终在计算中使用两个timeGetTime返回值之间的差。
19         /// timeGetTime函数的默认精度可以是5毫秒或更多,具体取决于机器。您可以使用timeBeginPeriod和timeEndPeriod函数来提高timeGetTime的精度。
20         /// 如果这样做,timeGetTime返回的连续值之间的最小差异可能与使用timeBeginPeriod和timeEndPeriod设置的最小周期值一样大。</remarks>
21         [DllImport("winmm", EntryPoint = "timeGetTime")]
22         public static extern uint TimeGetTime();
23 
24         /// <summary> 要求定期定时器的最小分辨率。 </summary>
25         /// <param name="uPeriod">应用程序或设备驱动程序的最小计时器分辨率(以毫秒为单位)。较低的值表示较高的(更准确的)分辨率。UINT </param>
26         /// <returns>返回TIMERR_NOERROR(0)如果成功或TIMERR_NOCANDO(97)如果在指定的分辨率uPeriod是超出范围。MMRESULT(uint)</returns>
27         [DllImport("winmm", EntryPoint = "timeBeginPeriod")]
28         public static extern uint TimeBeginPeriod(int uPeriod);
29 
30         /// <summary> 清除先前设定的最小计时器分辨率。 </summary>
31         /// <param name="uPeriod">在上一次调用timeBeginPeriod函数中指定的最小计时器分辨率。UINT </param>
32         /// <returns>返回TIMERR_NOERROR(0)如果成功或TIMERR_NOCANDO(97)如果在指定的分辨率uPeriod是超出范围。MMRESULT(uint)</returns>
33         [DllImport("winmm", EntryPoint = "timeEndPeriod")]
34         public static extern uint TimeEndPeriod(int uPeriod);
35 
36         /// <summary> 检索性能计数器的当前值,这是一个高分辨率(小于1us)时间戳,可用于时间间隔测量。 </summary>
37         /// <param name="lpPerformanceCount">指向接收当前性能计数器值(以计数为单位)的变量的指针。LARGE_INTEGER </param>
38         /// <returns>如果函数成功,则返回值为非零。如果函数失败,则返回值为零。要获取扩展的错误信息,请调用GetLastError。
39         /// 在运行Windows XP或更高版本的系统上,该函数将始终成功执行,因此永远不会返回零。</returns>
40         [DllImport("kernel32")]
41         public static extern short QueryPerformanceCounter(ref long lpPerformanceCount);
42 
43         /// <summary> 检索性能计数器的频率。性能计数器的频率在系统启动时是固定的,并且在所有处理器之间均保持一致。
44         /// 因此,只需要在应用程序初始化时查询频率,就可以缓存结果。</summary>
45         /// <param name="lpFrequency">指向接收当前性能计数器频率的变量的指针,以每秒计数为单位。LARGE_INTEGER </param>
46         /// <returns>如果安装的硬件支持高分辨率性能计数器,则返回值为非零。如果函数失败,则返回值为零。要获取扩展的错误信息,请调用GetLastError。
47         /// 在运行Windows XP或更高版本的系统上,该函数将始终成功执行,因此永远不会返回零。</returns>
48         [DllImport("kernel32")]
49         public static extern short QueryPerformanceFrequency(ref long lpFrequency);

 

获取或计算系统开机时间的方法:

 1        //测试处理器 i7-4700MQ 
 2             using (PerformanceCounter pc = new PerformanceCounter("System", "System Up Time")) {
 3                 pc.NextValue();    //The first call returns 0, so call this twice
 4                 float nextValue = pc.NextValue();
 5                 DateTime time = DateTime.Now;
 6                 Console.WriteLine(time.AddTicks(-TimeSpan.FromSeconds(nextValue).Ticks).ToString("O") + "  System Up Time");
 7             }
 8 
 9             SelectQuery query = new SelectQuery("SELECT LastBootUpTime FROM Win32_OperatingSystem WHERE Primary=‘true‘");
10             ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
11             foreach (ManagementBaseObject o in searcher.Get()) {
12                 ManagementObject mo = (ManagementObject)o;
13                 string date = mo.Properties["LastBootUpTime"].Value.ToString();
14                 DateTime dtBootTime = ManagementDateTimeConverter.ToDateTime(date);
15                 Console.WriteLine(dtBootTime.ToString("O") + "   SELECT LastBootUpTime FROM Win32_OperatingSystem ");
16             }
17 
18             //上面两个比QueryPerformanceCounter计算出来的快150ms左右
19 
20             long x = 0;
21             QueryPerformanceCounter(ref x);
22             Console.WriteLine(DateTime.Now.AddTicks(-x).ToString("O") + "   QueryPerformanceCounter ");
23 
24             //下面比QueryPerformanceCounter计算出来的慢160ms左右
25 
26             Console.WriteLine(DateTime.Now.AddMilliseconds(-Environment.TickCount).ToString("O") + "   Environment.TickCount ");
27             Console.WriteLine(DateTime.Now.AddMilliseconds(-GetTickCount()).ToString("O") + "   GetTickCount ");
28             Console.WriteLine(DateTime.Now.AddMilliseconds(-(long)GetTickCount64()).ToString("O") + "   GetTickCount64 ");
29             TimeBeginPeriod(1);
30             Console.WriteLine(DateTime.Now.AddMilliseconds(-TimeGetTime()).ToString("O") + "   TimeGetTime ");
31             TimeEndPeriod(1);
32             long z = 0;
33             QueryPerformanceCounter(ref x);
34             DateTime now = DateTime.Now;
35             QueryPerformanceCounter(ref z);
36             //DateTime.Now消耗大概1 - 3微秒
37             Console.WriteLine("DateTime.Now消耗(单位100ns):" + (z - x));
38             Console.ReadKey();

[.Net]windows获取开机时间和计时方法

[.Net]windows获取开机时间和计时方法

上一篇:C#检查硬盘容量


下一篇:[WPF]使用附加属性处理 ScrollViewer 的滚动轮劫持问题