2009-10-27 5 views
7

Есть ли способ узнать, когда система была последней остановкой?Получить дату-время последнего отключения Windows, используя .NET.

Я знаю, что есть способ, чтобы выяснить, в последний раз загрузиться время, используя LastBootUpTime свойства в Win32_OperatingSystem имен с использованием WMI.

Есть ли что-либо подобное, чтобы узнать о последнем отключении?

Спасибо.

+3

Вам также необходимо рассмотреть вопрос, беспокоит ли вас, когда машина потянула его сила - вы не получив для этого события. – serialhobbyist

ответ

8

(здесь все 100% любезно JDunkerley's earlier answer)

Решение выше, но подход перехода от массива byte к DateTime может быть достигнут с меньшим количеством операторов, используя BitConverter. Следующие шесть строк кода делают то же самое и дают правильный DateTime из реестра:

public static DateTime GetLastSystemShutdown() 
{ 
    string sKey = @"System\CurrentControlSet\Control\Windows"; 
    Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(sKey); 

    string sValueName = "ShutdownTime"; 
    byte[] val = (byte[]) key.GetValue(sValueName); 
    long valueAsLong = BitConverter.ToInt64(val, 0); 
    return DateTime.FromFileTime(valueAsLong); 
} 
+0

Хм, спасибо за принятие, но предоставленное здесь решение полностью основано на ответе JDunkerley, он должен получить все кредиты, в основном ;-) – Abel

+0

Кажется, что это Значение не обновляется при сбое компьютера :( – Pavenhimself

+1

@Pavenhimself: если компьютер выходит из строя, событие в журнале событий создается _after_ следующей загрузкой (сам BSOD, очевидно, предотвращает запись фактического Shutdowntime в реестр или что-то еще в этом случае единственное, что система делает для BSOD, - это создать файл дампа). Вы можете проверить EventID 6008, источник EventLog. Чтобы найти фактическое время, отметьте метку времени на Файл дампа BSOD. – Abel

8

Предполагая, что Windows выключена плавно. Он хранит его в реестре:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Windows\ShutdownTime 

Он хранится в виде массива байтов, но является FILETIME.

Хотя может быть лучший способ, я использовал это раньше, и думаю, что это работает:

public static DateTime GetLastSystemShutdown() 
    { 
     string sKey = @"System\CurrentControlSet\Control\Windows"; 
     Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(sKey); 

     string sValueName = "ShutdownTime"; 
     object val = key.GetValue(sValueName); 

     DateTime output = DateTime.MinValue; 
     if (val is byte[] && ((byte[])val).Length == 8) 
     { 
      byte[] bytes = (byte[])val; 

      System.Runtime.InteropServices.ComTypes.FILETIME ft = new System.Runtime.InteropServices.ComTypes.FILETIME(); 
      int valLow = bytes[0] + 256 * (bytes[1] + 256 * (bytes[2] + 256 * bytes[3])); 
      int valTwo = bytes[4] + 256 * (bytes[5] + 256 * (bytes[6] + 256 * bytes[7])); 
      ft.dwLowDateTime = valLow; 
      ft.dwHighDateTime = valTwo; 

      DateTime UTC = DateTime.FromFileTimeUtc((((long) ft.dwHighDateTime) << 32) + ft.dwLowDateTime); 
      TimeZoneInfo lcl = TimeZoneInfo.Local; 
      TimeZoneInfo utc = TimeZoneInfo.Utc; 
      output = TimeZoneInfo.ConvertTime(UTC, utc, lcl); 
     } 
     return output; 
    } 
+0

+1 Прекрасный подход, я удалил свой пост, так как это гораздо точнее, кажется – Abel

+0

Извините, я не удержался, кажется, есть немного более простой способ преобразования байтового массива в 'DateTime', надеюсь, t mind, но я не мог бы сделать это без вашего ответа :) – Abel

4

Последний Restart время можно найти, используя этот кусок кода

static void Main(string[] args) 
    {   
     TimeSpan t = TimeSpan.FromMilliseconds(System.Environment.TickCount); 
     Console.WriteLine(DateTime.Now.Subtract(t));   
    }