首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

如果获取进程CPU占用率,该如何处理

2012-04-05 
如果获取进程CPU占用率我有一段代码可以用TIMER来实现,但现在不能使用TIMER控件,需要直接调用函数后返回CP

如果获取进程CPU占用率
我有一段代码可以用TIMER来实现,但现在不能使用TIMER控件,需要直接调用函数后返回CPU使用率,请问该如何处理
代码如下:

unit   Unit1;

interface

uses
Windows,   Messages,   SysUtils,   Variants,   Classes,   Graphics,   Controls,   Forms,
Dialogs,   StdCtrls,   ExtCtrls;

type
TForm1   =   class(TForm)
        Button1:   TButton;
        Timer1:   TTimer;
        Label2:   TLabel;
        Edit1:   TEdit;
        procedure   Timer1Timer(Sender:   TObject);
        procedure   Button1Click(Sender:   TObject);
private
        {   Private   declarations   }
public
        {   Public   declarations   }
end;

var    
Form1:   TForm1;      
dtStart,   dtCPUStart:   Tdatetime;
hProcess:   THandle;      
iCount:integer;

implementation    
   
{$R   *.dfm}

function   AddFileTimes(Time1,   Time2:   TFileTime):   TDateTime;      
var
SysTime1,   SysTime2:   TSystemTime;
begin
FileTimeToSystemTime(Time1,   SysTime1);
FileTimeToSystemTime(Time2,   SysTime2);
Result   :=   SystemTimeToDateTime(SysTime1)   +   SystemTimeToDateTime(SysTime2);
end;

function   GetProcessCPU:   TDateTime;
var
CreationTime,   ExitTime,   KernelTime,   UserTime:   TFileTime;
begin
GetProcessTimes(GetCurrentProcess,   CreationTime,   ExitTime,   KernelTime,
UserTime);
Result   :=   AddFileTimes(KernelTime,   UserTime);
end;

procedure   TForm1.Timer1Timer(Sender:   TObject);
begin
if   (dtStart <> 0)   and   (dtCPUStart <> 0)   then
begin
        Label2.Caption:=FloatToStr(-1*((GetProcessCPU-dtCPUStart)*100/(now-dtStart)));

end;      
dtStart:=now;
dtCPUStart:=GetProcessCPU;
end;      
   
procedure   TForm1.Button1Click(Sender:   TObject);
begin
timer1.Enabled   :=   False;
iCount:=0;
dtStart:=0;
dtCPUStart:=0;
hProcess   :=   GetCurrentProcessId();
if   hProcess   >   0   then
        timer1.Enabled   :=   True;
end;
end.

[解决办法]

//------------------------------------------

const
Processor_IDX_Str = '238 ';
Processor_IDX = 238;
CPUUsageIDX = 6;

type
AInt64F = array[0..$FFFF] of TInt64F;
PAInt64F = ^AInt64F;

var
_PerfData: PPERF_DATA_BLOCK;
_BufferSize: Integer;
_POT: PPERF_OBJECT_TYPE;
_PCD: PPerf_Counter_Definition;
_ProcessorsCount: Integer;
_Counters: PAInt64F;
_PrevCounters: PAInt64F;
_SysTime: TInt64F;
_PrevSysTime: TInt64F;
_IsWinNT: Boolean;

_W9xCollecting: Boolean;
_W9xCpuUsage: DWORD;
_W9xCpuKey: HKEY;


//------------------------------------------

function GetCPUCount: Integer;
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;
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;
if Result > 1 then
Result := 1;
end;

var VI: TOSVERSIONINFO;

//------------------------------------------

procedure CollectCPUData;
var BS: integer;
i: Integer;
_PCB_Instance: PPERF_COUNTER_BLOCK;
_PID_Instance: PPERF_INSTANCE_DEFINITION;
ST: TFileTime;

var 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
// Get a buffer that is big enough.
INC(_BufferSize, $1000);
BS := _BufferSize;
ReallocMem(_PerfData, _BufferSize);
end;

// Locate the performance object
_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;

// Check for success
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;

// Locate the "% CPU usage " counter definition
_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;



// Check for success
if _PCD.CounterNameTitleIndex <> CPUUsageIDX then
raise Exception.Create( 'Unable to locate the "% of CPU usage " performance counter ');

// Collecting coutners
_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;

dwDataSize := sizeof(DWORD);
RegQueryValueEx(_W9xCpuKey, 'KERNEL\CPUUsage ', nil, @dwType, PBYTE(@_W9xCpuUsage), @dwDataSize);
end;
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;
finalization
ReleaseCPUData;
FreeMem(_PerfData);
end.

[解决办法]
HKEY_DYN_DATA的这个主键 'PerfStats\StartStat\KERNEL\CPUusage '
这个只在98下有效!
在NT下:你得先定义每一个进程的STARtime,PREtime,PREuse这样的一个CUP记录!
然后,再用以上的方法,刷新每一个进程的记录!才可以得到每一个进程的使作率,
哦就是这样实现的!

热点排行