Calculating Windows NT uptime with Delphi
Posted: (EET/GMT+2)
I was today testing if I could use Delphi to read the Windows NT Event Log and find the system startup event. It turned out this can be done, and here below is code that shows how this can be done.
The reading of events is done with the ReadEventLog Win32 API, and the event with id number 512 is the one to look for: "Windows NT is starting up." The time is returned as a long number that requires some calculation to become a Delphi TDateTime object.
The following code allows you to calculate the uptime:
Uses Messages,SysUtils,Windows;
Const
EventLog_Sequential_Read = $1;
EventLog_Backwards_Read = $8;
Type
PEventLogRecord = ^TEventLogRecord;
TEventLogRecord = Record
Length : Integer;
Reserved : Integer;
RecordNumber : Integer;
TimeGenerated : Integer;
TimeWritten : Integer;
EventID : Integer;
EventType : Word;
NumStrings : Word;
EventCategory : Word;
ReservedFlags : Word;
ClosingRecordNumber : Integer;
StringOffset : Integer;
UserSidLength : Integer;
UserSidOffset : Integer;
DataLength : Integer;
DataOffset : Integer;
{ optional data follows }
End;
Var
SystemStartupTime : TDateTime;
SystemName : String;
Function GetComputerUpTime : String;
Var RunTime : TDateTime;
Begin
RunTime := Now-SystemStartupTime+1;
Result := SystemName+IntToStr(Trunc(RunTime))+' day(s), '+TimeToStr(RunTime);
End;
Procedure ReadComputerName;
Var I : Integer;
Begin
I := 255;
SetLength(SystemName,I);
If GetComputerName(PChar(SystemName),I) Then Begin
SetLength(SystemName,I);
SystemName := SystemName+' has been running for ';
End
Else SystemName := '';
End;
Procedure ScanEventLogForStartupEvent;
Var
Log : THandle;
Buf : Array[0..5000-1] of Char;
BytesRead,MinBytes,Ofs : Integer;
Begin
Log := OpenEventLog(nil,'Security');
While (ReadEventLog(Log,EventLog_Backwards_Read Or EventLog_Sequential_Read,0,
@Buf,SizeOf(Buf),BytesRead,MinBytes)) do Begin
Ofs := 0;
While (BytesRead > 0) do Begin
With PEventLogRecord(@Buf[Ofs])^ do Begin
If (EventID = 512) Then Begin { "Windows NT is starting up." }
SystemStartupTime := (TimeGenerated / (60*60*24))+25569.08333333333;
CloseEventLog(Log);
Exit;
End;
Inc(Ofs,Length);
Dec(BytesRead,Length);
End;
End;
End;
CloseEventLog(Log);
MessageBox(0,'Cannot find system startup event from event log.','UpTime',mb_IconError+mb_OK);
Halt(2);
End;
For making the code run faster, I'm scanning the event log backwards, from newest entry to oldest.
To use the code, you would simply call the functions in order:
ReadComputerName(); ScanEventLogForStartupEvent(); WriteLn(GetComputerUpTime());
If it works, it should display your computer's name and the uptime in days.
What is the longest uptime you have had? Mine is about a week.