8 ответов:
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()); } } }
Я немного опоздал, но другой простой способ заключается в использовании GetTickCount64 функция, которая доступна начиная с Windows Vista и не переполняется, как GetTickCount делает:
public static TimeSpan GetUpTime() { return TimeSpan.FromMilliseconds(GetTickCount64()); } [DllImport("kernel32")] extern static UInt64 GetTickCount64();
моя машина имеет время безотказной работы
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но все еще совершенно точно по сравнению с диспетчером задач.обратите внимание, что я вычитал текущее затраченное время из каждого метода перед печатью times, но все это занимает менее 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}"); }
точнее и больше, чем
System.Environment.TickCount, не включая счетчики ОС, WMI или собственные вызовы:var ticks = Stopwatch.GetTimestamp(); var uptime = ((double)ticks) / Stopwatch.Frequency; var uptimeSpan = TimeSpan.FromSeconds(uptime);
самый простой и правильный способ сделать это -
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(); }
просто, нет, но это можно сделать:
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!"); }
Я знаю, что вопрос как старый, так и решенный, но самое лучшее решение, которое я могу придумать, - это просто использовать окружающую среду.Свойство TickCount, которое возвращает количество миллисекунд с момента запуска системы:
System.DateTime SystemStartTime = DateAndTime.Now.AddMilliseconds(-Environment.TickCount); System.DateTime Uptime = DateAndTime.Now - SystemStartTime;Это решение намного быстрее, чем принятое answare.
Comments