2009-10-27 6 views
7

C'è un modo per scoprire quando il sistema era ultima arresto?Prendi il data-ora delle finestre ultimo evento di arresto utilizzando .NET

So che c'è un modo per scoprire l'ultima tempo di avvio utilizzando la proprietàLastBootUpTime in Win32_OperatingSystem spazio dei nomi utilizzando WMI.

C'è qualcosa di simile per scoprire l'ultima volta l'arresto?

Grazie.

+3

Avrete anche bisogno di prendere in considerazione se si cura quando una macchina ha il suo potere tirato - sei non otterrò un evento per quello. – serialhobbyist

risposta

8

(qui tutto è al 100% per gentile concessione di JDunkerley's earlier answer)

La soluzione è sopra, ma l'approccio di passare da un array byte a DateTime può essere ottenuto con meno istruzioni usando lo BitConverter. Le seguenti sei righe di codice fanno lo stesso e danno il corretto DateTime dal Registro di sistema:

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

Hmm, grazie per aver accettato, ma la soluzione qui fornita è totalmente basata sulla risposta di JDunkerley, dovrebbe ricevere tutto il credito, in sostanza ;-) – Abel

+0

Sembra che questo valore non viene aggiornato quando il computer si blocca :( – Pavenhimself

+1

@Pavenhimself: se il computer si blocca, un evento nel registro eventi viene creato _after_ il prossimo avvio (il BSOD si impedisce, ovviamente, l'attuale Shutdowntime da scrivere nel registro di sistema, o qualsiasi altra cosa del resto, l'unica cosa che il sistema fa su BSOD è creare un file di dump. Puoi controllare EventID 6008, source EventLog. Per trovare l'ora esatta, controlla il timestamp sul File di dump BSOD. – Abel

8

Supponendo Windows è arresto senza intoppi. Lo memorizza nel Registro:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Windows\ShutdownTime 

essa viene memorizzata come una matrice di byte, ma è un FILETIME.

Mentre ci può essere un modo migliore, ho usato questo prima e penso che funziona:

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 bene approccio, ho cancellato il mio post, in quanto questo è di gran lunga più preciso sembra – Abel

+0

dispiace, non ho potuto resistere, sembra che ci sia modo leggermente più facile per convertire un array di byte a un 'DateTime', spero che don' t mente, ma non avrei potuto farlo senza la tua risposta :) – Abel

4

L'ultima volta che riavvio può essere trovato con questo pezzo di codice

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