使用C#检索系统正常运行时间

问题描述 投票:55回答:8

有没有一种简单的方法可以使用C#获得系统的正常运行时间?

c# .net windows uptime
8个回答
51
投票
public TimeSpan UpTime {
    get {
        using (var uptime = new PerformanceCounter("System", "System Up Time")) {
            uptime.NextValue();       //Call this an extra time before reading its value
            return TimeSpan.FromSeconds(uptime.NextValue());
        }
    }
}

39
投票

我有点迟了,但另一个简单的方法是使用GetTickCount64函数,该函数从Windows Vista开始可用,并且不会像GetTickCount那样溢出:

public static TimeSpan GetUpTime()
{
    return TimeSpan.FromMilliseconds(GetTickCount64());
}

[DllImport("kernel32")]
extern static UInt64 GetTickCount64();

26
投票

System.Environment.TickCount获取自系统重启以来的毫秒数。

请注意,它是一个Int32,并将在24.9天后溢出并将变为负数。请参阅MDSN文档上的备注。


17
投票

根据任务经理的说法,我的机器的正常运行时间为58 days 17 hours。我经历过并尝试了每个答案,快速的一点点关闭(约1-3分钟,但超过58天的正常运行时间):

Stopwatch.GetTimeStamp():                   58days 17hours 11minutes 25seconds
~Time to calculate (ms): 6.8413
DllImport GetTickCount64():                 58days 17hours 13minutes 34seconds
~Time to calculate (ms): 0.2192
PerformanceCounter(System, System Up Time): 58days 17hours 14minutes 02seconds
~Time to calculate (ms): 1233.2854
ManagementObject LastBootUpTime:            58days 17hours 14minutes 02seconds
~Time to calculate (ms): 30.0283

最后两个,使用PerformanceCounter或使用ManagementObject,始终与Windows任务管理器在同一秒内(只需要接受我的话,或者使用下面的代码自己尝试)。根据结果​​,我将使用ManagementObject LastBootUpTime方法,因为它比PerformanceCounter快得多,但与任务管理器相比仍然完全准确。

请注意,我确实在打印时间之前减去了每个方法的当前经过时间,但是整个过程运行时间不到2秒,因此无论如何都不能通过不正确地计算执行时间来解释时移。这是我使用的代码:

[System.Runtime.InteropServices.DllImport("kernel32")]
extern static UInt64 GetTickCount64();

public static void Main()
{
    var start = Stopwatch.StartNew();

    var eachStart = Stopwatch.StartNew();
    var ticks = Stopwatch.GetTimestamp();
    var uptime = ((double)ticks) / Stopwatch.Frequency;
    var uptimeTimeSpan = TimeSpan.FromSeconds(uptime);
    Console.WriteLine("Stopwatch.GetTimeStamp():                   " + uptimeTimeSpan.Subtract(start.Elapsed).ToString(@"dd\d\a\y\s\ hh\h\o\u\r\s\ mm\m\i\n\u\t\e\s\ ss\s\e\c\o\n\d\s"));
    Console.WriteLine($"~Time to calculate (ms): {eachStart.Elapsed.TotalMilliseconds}");

    eachStart.Restart();
    Console.WriteLine("DllImport GetTickCount64():                 " + TimeSpan.FromMilliseconds(GetTickCount64()).Subtract(start.Elapsed).ToString(@"dd\d\a\y\s\ hh\h\o\u\r\s\ mm\m\i\n\u\t\e\s\ ss\s\e\c\o\n\d\s"));
    Console.WriteLine($"~Time to calculate (ms): {eachStart.Elapsed.TotalMilliseconds}");

    eachStart.Restart();
    var upTime = new PerformanceCounter("System", "System Up Time");
    upTime.NextValue();       //Call this an extra time before reading its value
    Console.WriteLine("PerformanceCounter(System, System Up Time): " + TimeSpan.FromSeconds(upTime.NextValue()).Subtract(start.Elapsed).ToString(@"dd\d\a\y\s\ hh\h\o\u\r\s\ mm\m\i\n\u\t\e\s\ ss\s\e\c\o\n\d\s"));
    Console.WriteLine($"~Time to calculate (ms): {eachStart.Elapsed.TotalMilliseconds}");

    eachStart.Restart();
    ManagementObject mo = new ManagementObject(@"\\.\root\cimv2:Win32_OperatingSystem=@");
    DateTime lastBootUp = ManagementDateTimeConverter.ToDateTime(mo["LastBootUpTime"].ToString());
    Console.WriteLine("ManagementObject LastBootUpTime:            " + (DateTime.Now.ToUniversalTime() - lastBootUp.ToUniversalTime()).Subtract(start.Elapsed).ToString(@"dd\d\a\y\s\ hh\h\o\u\r\s\ mm\m\i\n\u\t\e\s\ ss\s\e\c\o\n\d\s"));
    Console.WriteLine($"~Time to calculate (ms): {eachStart.Elapsed.TotalMilliseconds}");
}

10
投票

精确和大于System.Environment.TickCount,不涉及操作系统可怕的性能计数器,WMI或本机调用:

var ticks = Stopwatch.GetTimestamp();
var uptime = ((double)ticks) / Stopwatch.Frequency;
var uptimeSpan = TimeSpan.FromSeconds(uptime);

7
投票

最简单和正确的方法是

public static TimeSpan GetUptime()
{
    ManagementObject mo = new ManagementObject(@"\\.\root\cimv2:Win32_OperatingSystem=@");
    DateTime lastBootUp = ManagementDateTimeConverter.ToDateTime(mo["LastBootUpTime"].ToString());
    return DateTime.Now.ToUniversalTime() - lastBootUp.ToUniversalTime();
}

4
投票

简单,不,但可以做到:

    static DateTime getLastBootTime(ManagementObject mObject)
    {
        PropertyData pd = mObject.Properties["LastBootUpTime"];
        string name = pd.Name.ToString();
        DateTime lastBoot = parseCmiDateTime(pd.Value.ToString());
        return lastBoot;
    }

    static ManagementObject getServerOSObject(string serverName)
    {
        ManagementObjectSearcher mSearcher = new ManagementObjectSearcher("Select * From Win32_OperatingSystem");
        mSearcher.Scope = new ManagementScope(String.Format(@"\\{0}\root\cimv2", serverName));
        ManagementObjectCollection mObjects = mSearcher.Get();
        if (mObjects.Count != 1) throw new Exception(String.Format("Expected 1 object, returned {0}.", mObjects.Count));
        foreach (ManagementObject m in mObjects)
        {
            //No indexing on collection
            return m;
        }
        throw new Exception("Something went wrong!");
    }

1
投票

我知道问题既旧又解决了,但我能说的最简单的解决方案就是使用Enviroment.TickCount属性,该属性返回自系统启动以来的毫秒数:

System.DateTime SystemStartTime = DateAndTime.Now.AddMilliseconds(-Environment.TickCount);
System.DateTime Uptime = DateAndTime.Now - SystemStartTime;

此解决方案比接受的答案快得多。

© www.soinside.com 2019 - 2024. All rights reserved.