首页  编辑  

系统已经运行了多长时间

Tags: /超级猛料/OS.操作系统/浏览器、系统/   Date Created:

系统已经运行了多长时间

////////////////////////////////////////////////////////////////////////////////

//

//  GetSystemUpTimeNt()

//

//    Uses the registry interface to get the value of the performance counter

//    '\\localhost\System\System Up Time' in milliseconds (returns 0 on error).

//

function GetSystemUpTimeNt(): Int64;

{$IFDEF WIN32}

type

 PPerfDataBlock = ^TPerfDataBlock;

 TPerfDataBlock = packed record

   Signature       : array [0..3] of WCHAR;

   LittleEndian    : DWORD;

   Version         : DWORD;

   Revision        : DWORD;

   TotalByteLength : DWORD;

   HeaderLength    : DWORD;

   NumObjectTypes  : DWORD;

   DefaultObject   : DWORD;

   SystemTime      : SYSTEMTIME;

   PerfTime        : LARGE_INTEGER;

   PerfFreq        : LARGE_INTEGER;

   PerfTime100nSec : LARGE_INTEGER;

   SystemNameLength: DWORD;

   SystemNameOffset: DWORD;

 end;

 PPerfObjectType = ^TPerfObjectType;

 TPerfObjectType = packed record

   TotalByteLength     : DWORD;

   DefinitionLength    : DWORD;

   HeaderLength        : DWORD;

   ObjectNameTitleIndex: DWORD;

   ObjectNameTitle     : LPWSTR;

   ObjectHelpTitleIndex: DWORD;

   ObjectHelpTitle     : LPWSTR;

   DetailLevel         : DWORD;

   NumCounters         : DWORD;

   DefaultCounter      : DWORD;

   NumInstances        : DWORD;

   CodePage            : DWORD;

   PerfTime            : LARGE_INTEGER;

   PerfFreq            : LARGE_INTEGER;

 end;

 PPerfCounterDefinition = ^TPerfCounterDefinition;

 TPerfCounterDefinition = packed record

   ByteLength           : DWORD;

   CounterNameTitleIndex: DWORD;

   CounterNameTitle     : LPWSTR;

   CounterHelpTitleIndex: DWORD;

   CounterHelpTitle     : LPWSTR;

   DefaultScale         : DWORD;

   DetailLevel          : DWORD;

   CounterType          : DWORD;

   CounterSize          : DWORD;

   CounterOffset        : DWORD;

 end;

 PPerfInstanceDefinition = ^TPerfInstanceDefinition;

 TPerfInstanceDefinition = packed record

   ByteLength            : DWORD;

   ParentObjectTitleIndex: DWORD;

   ParentObjectInstance  : DWORD;

   UniqueID              : DWORD;

   NameOffset            : DWORD;

   NameLength            : DWORD;

 end;

 PLARGE_INTEGER = ^LARGE_INTEGER;

const

 PERF_SIZE_LARGE      = $00000100;

 PERF_TYPE_COUNTER    = $00000400;

 PERF_COUNTER_ELAPSED = $00040000;

 PERF_OBJECT_TIMER    = $00200000;

 PERF_DISPLAY_SECONDS = $30000000;

 PERF_ELAPSED_TIME    = PERF_SIZE_LARGE or PERF_TYPE_COUNTER or

                        PERF_COUNTER_ELAPSED or PERF_OBJECT_TIMER or

                        PERF_DISPLAY_SECONDS;

 PERF_NO_INSTANCES = DWORD(-1);

var

 ValSize: DWORD;

 Counter: PChar;

 CurrIdx: PChar;

 CurrStr: PChar;

 CntrStr: PChar;

 CntrSys: DWORD;

 CntrSUT: DWORD;

 QrySize: DWORD;

 QryData: PPerfDataBlock;

 CurrObj: PPerfObjectType;

 ObjLoop: DWORD;

 CurrDef: PPerfCounterDefinition;

 DefLoop: DWORD;

 ObjInst: PPerfInstanceDefinition;

 CntrVal: PLARGE_INTEGER;

{$ENDIF}

begin

 Result := 0;  // indicates failure

{$IFDEF WIN32}

 ValSize := 0;

 if (RegQueryValueEx(HKEY_PERFORMANCE_DATA, 'Counter 009', nil, nil, nil,

   @ValSize) = ERROR_SUCCESS) then

 try

   Inc(ValSize, 1024);

   Counter := GetMemory(ValSize);

   if (Counter <> nil) then

   try

     if (RegQueryValueEx(HKEY_PERFORMANCE_DATA, 'Counter 009', nil, nil,

       PByte(Counter), @ValSize) = ERROR_SUCCESS) then

     begin

       CntrStr := nil;

       CntrSys := 0;

       CntrSUT := 0;

       CurrIdx := Counter;

       while (CurrIdx[0] <> #0) do

       begin

         CurrStr := PChar(@CurrIdx[StrLen(CurrIdx) + 1]);

         if ((CntrSys = 0) and (StrComp(CurrStr, 'System') = 0)) then

         begin

           CntrStr := CurrIdx;

           CntrSys := StrToInt(string(CurrIdx));

           if (CntrSUT <> 0) then

             Break;

         end;

         if ((CntrSUT = 0) and (StrComp(CurrStr, 'System Up Time') = 0)) then

         begin

           CntrSUT := StrToInt(string(CurrIdx));

           if (CntrSys <> 0) then

             Break;

         end;

         CurrIdx := PChar(@CurrStr[StrLen(CurrStr) + 1]);

       end;

       if ((CntrStr <> nil) and (CntrSys <> 0) and (CntrSUT <> 0)) then

       begin

         QrySize := 0;

         QryData := nil;

         try

           repeat

             Inc(QrySize, 4096);

             QryData := ReallocMemory(QryData, QrySize);

             if (QryData = nil) then

               Break;

             ValSize := QrySize;

           until (RegQueryValueEx(HKEY_PERFORMANCE_DATA, CntrStr, nil, nil,

             PByte(QryData), @ValSize) <> ERROR_MORE_DATA);

           if ((ValSize > 0) and (QryData <> nil)) then

             if (QryData.Signature = 'PERF') then

             begin

               CurrObj := PPerfObjectType(Cardinal(QryData) +

                 QryData.HeaderLength);

               for ObjLoop := 1 to QryData.NumObjectTypes do

               begin

                 if ((CurrObj.ObjectNameTitleIndex = CntrSys) and

                   (CurrObj.NumInstances > 0) and

                   (CurrObj.PerfFreq.QuadPart >= 1000)) then

                 begin

                   CurrDef := PPerfCounterDefinition(Cardinal(CurrObj) +

                     CurrObj.HeaderLength);

                   for DefLoop := 1 to CurrObj.NumCounters do

                   begin

                     if (CurrDef.CounterNameTitleIndex = CntrSUT) and

                       (CurrDef.CounterType = PERF_ELAPSED_TIME) then

                     begin

                       if (CurrObj.NumInstances = PERF_NO_INSTANCES) then

                         CntrVal := PLARGE_INTEGER(Cardinal(CurrObj) +

                            CurrObj.DefinitionLength + CurrDef.CounterOffset)

                       else

                       begin

                         // first instance

                         ObjInst := PPerfInstanceDefinition(Cardinal(CurrObj) +

                           CurrObj.DefinitionLength);

                         CntrVal := PLARGE_INTEGER(Cardinal(ObjInst) +

                            ObjInst.ByteLength + CurrDef.CounterOffset);

                       end;

                       Result :=

                         (CurrObj.PerfTime.QuadPart - CntrVal.QuadPart) div

                         (CurrObj.PerfFreq.QuadPart div 1000);  // milliseconds

                       Break;

                     end;

                     CurrDef := PPerfCounterDefinition(Cardinal(CurrDef) +

                       CurrDef.ByteLength);

                   end;

                   Break;

                 end;

                 CurrObj := PPerfObjectType(Cardinal(CurrObj) +

                   CurrObj.TotalByteLength);

               end;

             end;

         finally

           if (QryData <> nil) then

             FreeMemory(QryData);

         end;

       end;

     end;

   finally

     FreeMemory(Counter);

   end;

 finally

   RegCloseKey(HKEY_PERFORMANCE_DATA);

 end;

{$ENDIF}

end;

////////////////////////////////////////////////////////////////////////////////

//

//  GetSystemUpTime9x()

//

//    Uses GetTickCount() to get the 'System Up Time' in milliseconds.

//    Will wrap around to zero if the system is run continuously for 49.7 days!

//

function GetSystemUpTime9x(): Int64;

begin

{$IFDEF WIN32}

 Result := GetTickCount();

{$ELSE}

 Result := 0;

{$ENDIF}

end;

////////////////////////////////////////////////////////////////////////////////

//

//  GetSystemUpTime()

//

//    Wrapper for GetSystemUpTimeNt() and GetSystemUpTime9x()

//

function GetSystemUpTime(): Int64;

begin

 Result := GetSystemUpTimeNt();

 if (Result = 0) then

   Result := GetSystemUpTime9x();

end;

procedure TForm1.Button1Click(Sender: TObject);

var

 UpTimeNt: Int64;

 UpTime9x: Int64;

begin

 UpTime9x := GetSystemUpTime9x();

 UpTimeNt := GetSystemUpTimeNt();

 ShowMessage(Format('GetTickCount: %d day(s) %2.2d:%2.2d:%2.2d.%3.3d'#10 +

   'Perf-Counter: %d day(s) %2.2d:%2.2d:%2.2d.%3.3d', [UpTime9x div 86400000,

   UpTime9x mod 86400000 div 3600000, UpTime9x mod 3600000 div 60000,

   UpTime9x mod 60000 div 1000, UpTime9x mod 1000, UpTimeNt div 86400000,

   UpTimeNt mod 86400000 div 3600000, UpTimeNt mod 3600000 div 60000,

   UpTimeNt mod 60000 div 1000, UpTimeNt mod 1000]));

end;

Nico Bendlin