{==================================================================} { Get Memory And Cpu Informations Utils } {==================================================================}
{$ifdef ver130} {$L-} // The L+ causes internal error in Delphi 5 compiler {$O-} // The O+ causes internal error in Delphi 5 compiler {$Y-} // The Y+ causes internal error in Delphi 5 compiler {$endif}
{$ifndef ver110} type TInt64F = TInt64; {$else} type TInt64F = Extended; {$endif}
{$ifdef ver110} function FInt64(Value: TInt64): TInt64F; function Int64D(Value: DWORD): TInt64; {$else} type FInt64 = TInt64F; Int64D = TInt64; {$endif}
{$ifdef ver110} function FInt64(Value: TInt64): TInt64F; Var V: TInt64; begin if (Value.HighPart and $80000000) = 0 then // positive value begin result:=Value.HighPart; result:=result*$10000*$10000; result:=result+Value.LowPart; end else begin V.HighPart:=Value.HighPart xor $FFFFFFFF; V.LowPart:=Value.LowPart xor $FFFFFFFF; result:= -1 - FInt64(V); end; end;
function Int64D(Value: DWORD): TInt64; begin Result.LowPart:=Value; Result.HighPart := 0; // positive only end; {$endif}
function GetMemoryUsage : Double; { 返回内存当前使用率 总的是100%,传回的是0-100%间的使用率,可以自己做转换。 } Var msMemory : TMemoryStatus; begin try msMemory.dwLength := SizeOf(msMemory); GlobalMemoryStatus(msMemory); Result := msMemory.dwMemoryLoad; except Result := 0; end; end;
function GetCPUCount: Integer; { 获取CPU数量 } begin if _IsWinNT then begin if _ProcessorsCount < 0 then CollectCPUData; Result:=_ProcessorsCount; end else begin Result:=1; end; end;
procedure ReleaseCPUData; Var H: HKEY; R: DWORD; DwDataSize, DwType: DWORD; begin if _IsWinNT then Exit; if Not _W9xCollecting then Exit; _W9xCollecting := False; RegCloseKey(_W9xCpuKey); R := RegOpenKeyEx( HKEY_DYN_DATA, 'PerfStats\StopStat', 0, KEY_ALL_ACCESS, H); if R <> ERROR_SUCCESS then Exit; dwDataSize := Sizeof(DWORD); RegQueryValueEx(H,'KERNEL\CPUUsage', Nil, @DwType, PBYTE(@_W9xCpuUsage), @DwDataSize); RegCloseKey(H); end;
function GetCPUUsage(Index: Integer): Double; { 获取CPU当前使用率 } begin if _IsWinNT then begin if _ProcessorsCount < 0 then CollectCPUData; if (Index >= _ProcessorsCount) Or (Index < 0) then Raise Exception.Create('CPU index out of bounds'); if _PrevSysTime = _SysTime then Result := 0 else Result := 1-(_Counters[index] - _PrevCounters[index])/(_SysTime-_PrevSysTime); end else begin if Index <> 0 then Raise Exception.Create('CPU index out of bounds'); if Not _W9xCollecting then CollectCPUData; Result := _W9xCpuUsage/100; end; end;
Var VI: TOSVERSIONINFO;
procedure CollectCPUData; Var BS, i : Integer; _PCB_Instance : PPERF_COUNTER_BLOCK; _PID_Instance : PPERF_INSTANCE_DEFINITION; ST : TFileTime; H : HKEY; R : DWORD; DwDataSize, dwType: DWORD; begin if _IsWinNT then begin BS:=_BufferSize; while RegQueryValueEx( HKEY_PERFORMANCE_DATA, Processor_IDX_Str, nil, nil, PByte(_PerfData), @BS ) = ERROR_MORE_DATA do begin INC(_BufferSize,$1000); BS:=_BufferSize; ReallocMem( _PerfData, _BufferSize ); end;
_POT := PPERF_OBJECT_TYPE(DWORD(_PerfData) + _PerfData.HeaderLength); for i := 1 to _PerfData.NumObjectTypes do begin if _POT.ObjectNameTitleIndex = Processor_IDX then Break; _POT := PPERF_OBJECT_TYPE(DWORD(_POT) + _POT.TotalByteLength); end;
if _POT.ObjectNameTitleIndex <> Processor_IDX then Raise Exception.Create('Unable to locate the "Processor" performance object');
if _ProcessorsCount < 0 then begin _ProcessorsCount:=_POT.NumInstances; GetMem(_Counters,_ProcessorsCount*SizeOf(TInt64)); GetMem(_PrevCounters,_ProcessorsCount*SizeOf(TInt64)); end;
_PCD := PPERF_Counter_DEFINITION(DWORD(_POT) + _POT.HeaderLength); for i := 1 to _POT.NumCounters do begin if _PCD.CounterNameTitleIndex = CPUUsageIDX then Break; _PCD := PPERF_COUNTER_DEFINITION(DWORD(_PCD) + _PCD.ByteLength); end;
if _PCD.CounterNameTitleIndex <> CPUUsageIDX then Raise Exception.Create('Unable to locate the "% of CPU usage" performance counter');
_PID_Instance := PPERF_INSTANCE_DEFINITION(DWORD(_POT) + _POT.DefinitionLength); for i := 0 to _ProcessorsCount-1 do begin _PCB_Instance := PPERF_COUNTER_BLOCK(DWORD(_PID_Instance) + _PID_Instance.ByteLength); _PrevCounters[i]:=_Counters[i]; _Counters[i]:=FInt64(PInt64(DWORD(_PCB_Instance) + _PCD.CounterOffset)^); _PID_Instance := PPERF_INSTANCE_DEFINITION(DWORD(_PCB_Instance) + _PCB_Instance.ByteLength); end;
_PrevSysTime:=_SysTime; SystemTimeToFileTime(_PerfData.SystemTime, ST); _SysTime:=FInt64(TInt64(ST)); end else begin if Not _W9xCollecting then begin R:=RegOpenKeyEx( HKEY_DYN_DATA, 'PerfStats\StartStat', 0, KEY_ALL_ACCESS, H ); if R <> ERROR_SUCCESS then Raise Exception.Create('Unable to start performance monitoring'); dwDataSize:=sizeof(DWORD); RegQueryValueEx( H, 'KERNEL\CPUUsage', nil, @dwType, PBYTE(@_W9xCpuUsage), @dwDataSize ); RegCloseKey(H); R:=RegOpenKeyEx( HKEY_DYN_DATA, 'PerfStats\StatData', 0,KEY_READ, _W9xCpuKey ); if R <> ERROR_SUCCESS then Raise Exception.Create('Unable to read performance data'); _W9xCollecting:=True; end;
initialization _ProcessorsCount:= -1; _BufferSize:= $2000; _PerfData := AllocMem(_BufferSize); VI.dwOSVersionInfoSize := SizeOf(VI); if Not GetVersionEx(VI) then Raise Exception.Create('Can''t get the Windows version'); _IsWinNT := VI.dwPlatformId = VER_PLATFORM_WIN32_NT;