Som*_*one 5 delphi cpu performancecounter delphi-xe
我试图获得总CPU使用率的百分比 label1.Caption
我搜索过并找到了这些:
不起作用 - http://www.vbforums.com/showthread.php?345723-DELPHI-Get-CPU-Usage
不是我需要的 - http://delphi.cjcsoft.net/viewthread.php?tid=42837
这就是我正在做的事情:
我相信有一种简单的方法就像我们使用RAM一样.
GlobalMemoryStatus(RamStats);
Label1.Caption := Format('RAM: %d %%', [RamStats.dwMemoryLoad]);
Run Code Online (Sandbox Code Playgroud)
我找到了一篇文章,确定-cpu-usage-of-current-process-c-and-c,关于如何获取当前进程的CPU使用率.
现在,我们需要通过为每个正在运行的进程累加CPU使用百分比来计算总CPU使用率百分比:
function GetTotalCpuUsagePct(): Double;
var
ProcessID: TProcessID;
RunningProcessIDs : TArray<TProcessID>;
begin
Result := 0.0;
RunningProcessIDs := GetRunningProcessIDs;
DeleteNonExistingProcessIDsFromCache(RunningProcessIDs);
for ProcessID in RunningProcessIDs do
Result := Result + GetProcessCpuUsagePct( ProcessID );
end;
Run Code Online (Sandbox Code Playgroud)
在获得运行进程ID之后,我们开始调用
DeleteNonExistingProcessIDsFromCache清理缓存,该缓存保留了以前所需的Cpu使用时间GetProcessCpuUsagePct:自上次查询以来已停止的每个进程都从此缓存中删除.
它GetProcessCpuUsagePct是核心,它是Determ-cpu-usage-of-current-process-c-and-c的翻译.此函数需要LatestProcessCpuUsageCache使用ProcessID 从Cpu Usage Cache (单元中的全局)中检索先前的读取.注意,建议GetToalCpuUsageCpu不要每隔200毫秒调用一次,因为它可能会给出错误的结果.
function GetProcessCpuUsagePct(ProcessID: TProcessID): Double;
function SubtractFileTime(FileTime1: TFileTIme; FileTime2: TFileTIme): TFileTIme;
begin
Result := TFileTIme(Int64(FileTime1) - Int64(FileTime2));
end;
var
ProcessCpuUsage: TProcessCpuUsage;
ProcessHandle: THandle;
SystemTimes: TSystemTimesRec;
SystemDiffTimes: TSystemTimesRec;
ProcessDiffTimes: TProcessTimesRec;
ProcessTimes: TProcessTimesRec;
SystemTimesIdleTime: TFileTime;
ProcessTimesCreationTime: TFileTime;
ProcessTimesExitTime: TFileTime;
begin
Result := 0.0;
LatestProcessCpuUsageCache.TryGetValue(ProcessID, ProcessCpuUsage);
if ProcessCpuUsage = nil then
begin
ProcessCpuUsage := TProcessCpuUsage.Create;
LatestProcessCpuUsageCache.Add(ProcessID, ProcessCpuUsage);
end;
// method from:
// http://www.philosophicalgeek.com/2009/01/03/determine-cpu-usage-of-current-process-c-and-c/
ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ProcessID);
if ProcessHandle <> 0 then
begin
try
if GetSystemTimes(SystemTimesIdleTime, SystemTimes.KernelTime, SystemTimes.UserTime) then
begin
SystemDiffTimes.KernelTime := SubtractFileTime(SystemTimes.KernelTime, ProcessCpuUsage.LastSystemTimes.KernelTime);
SystemDiffTimes.UserTime := SubtractFileTime(SystemTimes.UserTime, ProcessCpuUsage.LastSystemTimes.UserTime);
ProcessCpuUsage.LastSystemTimes := SystemTimes;
if GetProcessTimes(ProcessHandle, ProcessTimesCreationTime, ProcessTimesExitTime, ProcessTimes.KernelTime, ProcessTimes.UserTime) then
begin
ProcessDiffTimes.KernelTime := SubtractFileTime(ProcessTimes.KernelTime, ProcessCpuUsage.LastProcessTimes.KernelTime);
ProcessDiffTimes.UserTime := SubtractFileTime(ProcessTimes.UserTime, ProcessCpuUsage.LastProcessTimes.UserTime);
ProcessCpuUsage.LastProcessTimes := ProcessTimes;
if (Int64(SystemDiffTimes.KernelTime) + Int64(SystemDiffTimes.UserTime)) > 0 then
Result := (Int64(ProcessDiffTimes.KernelTime) + Int64(ProcessDiffTimes.UserTime)) / (Int64(SystemDiffTimes.KernelTime) + Int64(SystemDiffTimes.UserTime)) * 100;
end;
end;
finally
CloseHandle(ProcessHandle);
end;
end;
end;
Run Code Online (Sandbox Code Playgroud)
以下是Windows 7上结果的屏幕截图.
完整的单位清单:
unit uTotalCpuUsagePct;
interface
function GetTotalCpuUsagePct : Double;
implementation
uses
SysUtils, DateUtils, Windows, PsAPI, TlHelp32, ShellAPI, Generics.Collections;
type
TProcessID = DWORD;
TSystemTimesRec = record
KernelTime: TFileTIme;
UserTime: TFileTIme;
end;
TProcessTimesRec = record
KernelTime: TFileTIme;
UserTime: TFileTIme;
end;
TProcessCpuUsage = class
LastSystemTimes: TSystemTimesRec;
LastProcessTimes: TProcessTimesRec;
ProcessCPUusagePercentage: Double;
end;
TProcessCpuUsageList = TObjectDictionary<TProcessID, TProcessCpuUsage>;
var
LatestProcessCpuUsageCache : TProcessCpuUsageList;
LastQueryTime : TDateTime;
(* -------------------------------------------------------------------------- *)
function GetRunningProcessIDs: TArray<TProcessID>;
var
SnapProcHandle: THandle;
ProcEntry: TProcessEntry32;
NextProc: Boolean;
begin
SnapProcHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if SnapProcHandle <> INVALID_HANDLE_VALUE then
begin
try
ProcEntry.dwSize := SizeOf(ProcEntry);
NextProc := Process32First(SnapProcHandle, ProcEntry);
while NextProc do
begin
SetLength(Result, Length(Result) + 1);
Result[Length(Result) - 1] := ProcEntry.th32ProcessID;
NextProc := Process32Next(SnapProcHandle, ProcEntry);
end;
finally
CloseHandle(SnapProcHandle);
end;
TArray.Sort<TProcessID>(Result);
end;
end;
(* -------------------------------------------------------------------------- *)
function GetProcessCpuUsagePct(ProcessID: TProcessID): Double;
function SubtractFileTime(FileTime1: TFileTIme; FileTime2: TFileTIme): TFileTIme;
begin
Result := TFileTIme(Int64(FileTime1) - Int64(FileTime2));
end;
var
ProcessCpuUsage: TProcessCpuUsage;
ProcessHandle: THandle;
SystemTimes: TSystemTimesRec;
SystemDiffTimes: TSystemTimesRec;
ProcessDiffTimes: TProcessTimesRec;
ProcessTimes: TProcessTimesRec;
SystemTimesIdleTime: TFileTime;
ProcessTimesCreationTime: TFileTime;
ProcessTimesExitTime: TFileTime;
begin
Result := 0.0;
LatestProcessCpuUsageCache.TryGetValue(ProcessID, ProcessCpuUsage);
if ProcessCpuUsage = nil then
begin
ProcessCpuUsage := TProcessCpuUsage.Create;
LatestProcessCpuUsageCache.Add(ProcessID, ProcessCpuUsage);
end;
// method from:
// http://www.philosophicalgeek.com/2009/01/03/determine-cpu-usage-of-current-process-c-and-c/
ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ProcessID);
if ProcessHandle <> 0 then
begin
try
if GetSystemTimes(SystemTimesIdleTime, SystemTimes.KernelTime, SystemTimes.UserTime) then
begin
SystemDiffTimes.KernelTime := SubtractFileTime(SystemTimes.KernelTime, ProcessCpuUsage.LastSystemTimes.KernelTime);
SystemDiffTimes.UserTime := SubtractFileTime(SystemTimes.UserTime, ProcessCpuUsage.LastSystemTimes.UserTime);
ProcessCpuUsage.LastSystemTimes := SystemTimes;
if GetProcessTimes(ProcessHandle, ProcessTimesCreationTime, ProcessTimesExitTime, ProcessTimes.KernelTime, ProcessTimes.UserTime) then
begin
ProcessDiffTimes.KernelTime := SubtractFileTime(ProcessTimes.KernelTime, ProcessCpuUsage.LastProcessTimes.KernelTime);
ProcessDiffTimes.UserTime := SubtractFileTime(ProcessTimes.UserTime, ProcessCpuUsage.LastProcessTimes.UserTime);
ProcessCpuUsage.LastProcessTimes := ProcessTimes;
if (Int64(SystemDiffTimes.KernelTime) + Int64(SystemDiffTimes.UserTime)) > 0 then
Result := (Int64(ProcessDiffTimes.KernelTime) + Int64(ProcessDiffTimes.UserTime)) / (Int64(SystemDiffTimes.KernelTime) + Int64(SystemDiffTimes.UserTime)) * 100;
end;
end;
finally
CloseHandle(ProcessHandle);
end;
end;
end;
(* -------------------------------------------------------------------------- *)
procedure DeleteNonExistingProcessIDsFromCache(const RunningProcessIDs : TArray<TProcessID>);
var
FoundKeyIdx: Integer;
Keys: TArray<TProcessID>;
n: Integer;
begin
Keys := LatestProcessCpuUsageCache.Keys.ToArray;
for n := Low(Keys) to High(Keys) do
begin
if not TArray.BinarySearch<TProcessID>(RunningProcessIDs, Keys[n], FoundKeyIdx) then
LatestProcessCpuUsageCache.Remove(Keys[n]);
end;
end;
(* -------------------------------------------------------------------------- *)
function GetTotalCpuUsagePct(): Double;
var
ProcessID: TProcessID;
RunningProcessIDs : TArray<TProcessID>;
begin
Result := 0.0;
RunningProcessIDs := GetRunningProcessIDs;
DeleteNonExistingProcessIDsFromCache(RunningProcessIDs);
for ProcessID in RunningProcessIDs do
Result := Result + GetProcessCpuUsagePct( ProcessID );
end;
(* -------------------------------------------------------------------------- *)
initialization
LatestProcessCpuUsageCache := TProcessCpuUsageList.Create( [ doOwnsValues ] );
// init:
GetTotalCpuUsagePct;
finalization
LatestProcessCpuUsageCache.Free;
end.
Run Code Online (Sandbox Code Playgroud)
测试代码:
单位Unit1;
interface
uses
Vcl.Forms, System.SysUtils, Vcl.Controls, Vcl.StdCtrls, System.Classes,
Vcl.ExtCtrls,
uTotalCpuUsagePct;
type
TForm1 = class(TForm)
Timer1: TTimer;
Label1: TLabel;
procedure Timer1Timer(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
// start cpu load thread
TThread.CreateAnonymousThread(
procedure
begin
while True do
begin
end;
end).Start;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
TotalCPUusagePercentage: Double;
begin
TotalCPUusagePercentage := GetTotalCpuUsagePct();
Label1.Caption := 'Total cpu: ' + IntToStr(Round(TotalCPUusagePercentage)) + '%';
end;
end.
Run Code Online (Sandbox Code Playgroud)
您可以使用Microsoft 的性能计数器功能来实现您的目标。
有限的用户访问支持
只有计算机的管理员或“性能日志用户组”中的用户才能记录和查看计数器数据。只有从用于以管理员身份运行打开的命令提示符窗口中启动了用于记录和查看计数器数据的工具,管理员组中的用户才可以记录和查看计数器数据。性能监视用户组中的用户可以查看计数器数据。
我从Lanzelot用户那里找到了这个答案 -查看当前使用的CPU-在SO上,我已经做了一些移植到Delphi的工作。
原始移植:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
pdh in 'pdh.pas';
var
cpuQuery: HQUERY;
cpuTotal: HCOUNTER;
i: Integer;
procedure init;
begin
PdhOpenQuery(nil, 0, cpuQuery);
PdhAddCounter(cpuQuery, '\Processor(_Total)\% Processor Time', 0, cpuTotal);
PdhCollectQueryData(cpuQuery);
end;
function getCurrentValue: Double;
var
counterVal: TPdhFmtCounterValue;
begin
PdhCollectQueryData(cpuQuery);
PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, nil, counterVal);
Result := counterVal.doubleValue;
end;
Run Code Online (Sandbox Code Playgroud)
该示例需要pdh我从此处获取的单元。
该WinPerf单元是必需的pdh,我已从此处下载了该单元。
控制台应用程序中的基本测试:
begin
init;
for i := 1 to 60 do begin
//let's monitor the CPU usage for one minute
WriteLn(getCurrentValue);
Sleep(1000);
end;
PdhCloseQuery(cpuQuery);
end.
Run Code Online (Sandbox Code Playgroud)
一个基于TThread类的更有用的示例。
这允许基于传递给ACounterPath构造函数中的参数的参数获得不同的计数器。
counterThread.pas
unit counterThread;
interface
uses
Classes, Windows, SyncObjs, pdh;
type
TCounterNotifyEvent = procedure(AValue: Double) of object;
TCounterThread = class(TThread)
private
FInterval: Integer;
FWaitEvent: TEvent;
FHQuery: HQUERY;
FHCounter: HCOUNTER;
procedure checkSuccess(AResult: Integer);
protected
procedure Execute; override;
procedure TerminatedSet; override;
public
OnCounter: TCounterNotifyEvent;
constructor Create(const ACounterPath: PChar; AInterval: Cardinal; ACreateSuspended: Boolean);
destructor Destroy; override;
end;
implementation
uses
SysUtils;
procedure TCounterThread.checkSuccess(AResult: Integer);
begin
if ERROR_SUCCESS <> AResult then
RaiseLastOSError;
end;
constructor TCounterThread.Create(const ACounterPath: PChar; AInterval: Cardinal; ACreateSuspended: Boolean);
begin
inherited Create(ACreateSuspended);
FInterval := AInterval;
FWaitEvent := TEvent.Create(nil, False, False, '');
FHQuery := INVALID_HANDLE_VALUE;
checkSuccess(PdhOpenQuery(nil, 0, FHQuery));
checkSuccess(PdhAddCounter(FHQuery, ACounterPath, 0, FHCounter));
//checkSuccess(PdhAddEnglishCounter(FHQuery, ACounterPath, 0, FHCounter));
checkSuccess(PdhCollectQueryData(FHQuery));
end;
destructor TCounterThread.Destroy;
begin
FWaitEvent.Free;
if (FHQuery <> 0) and (FHQuery <> INVALID_HANDLE_VALUE) then
PdhCloseQuery(FHQuery);
inherited;
end;
procedure TCounterThread.TerminatedSet;
begin
inherited;
FWaitEvent.SetEvent;
end;
procedure TCounterThread.Execute;
var
counterVal: TPdhFmtCounterValue;
begin
inherited;
while not Terminated do begin
checkSuccess(PdhCollectQueryData(FHQuery));
FillChar(counterVal, SizeOf(TPdhFmtCounterValue), 0);
checkSuccess(PdhGetFormattedCounterValue(FHCounter, PDH_FMT_DOUBLE, nil, counterVal));
if Assigned(OnCounter) then
OnCounter(counterVal.doubleValue);
FWaitEvent.WaitFor(FInterval);
end;
end;
end.
Run Code Online (Sandbox Code Playgroud)
单位1
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,
counterThread;
type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
FCpuCounter: TCounterThread;
procedure CpuCounterCounter(AValue: Double);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
FCpuCounter := TCounterThread.Create('\Processor(_Total)\% Processor Time', 1000, False);
//'\Processore(_Total)\% Tempo Processore'
with FCpuCounter do begin
FreeOnTerminate := True;
OnCounter := CpuCounterCounter;
end;
Button1.Enabled := False;
end;
procedure TForm1.CpuCounterCounter(AValue: Double);
begin
Edit1.Text := FloatToStr(AValue);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
if Assigned(FCpuCounter) then
FCpuCounter.Terminate;
end;
end.
Run Code Online (Sandbox Code Playgroud)
Unit1.dfm
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 123
ClientWidth = 239
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 8
Top = 24
Width = 97
Height = 13
Caption = 'Total CPU usage %:'
end
object Edit1: TEdit
Left = 111
Top = 21
Width = 99
Height = 21
TabOrder = 0
end
object Button1: TButton
Left = 111
Top = 80
Width = 99
Height = 25
Caption = 'Start monitoring'
TabOrder = 1
OnClick = Button1Click
end
end
Run Code Online (Sandbox Code Playgroud)
主题关闭
我目前在家里,但我这里没有Delphi XE,所以我用Turbo Delphi对其进行了编码,pdh我的机器上没有安装任何装置,目前我不知道Delphi XE是否装有这些装置。
注意
我已使用PdhAddCounter函数而不是PdhAddEnglishCounter,因为该单元中缺少函数引用。不幸的是,在添加参考之后,Pdh.dll旧的Windows XP中仍缺少该功能。
该szFullCounterPath的PdhAddCounter本地化,所以我必须用我的Windows意大利本地化的路径\Processore(_Total)\% Tempo Processore。
如果您使用此PdhAddEnglishCounter功能,或者您的语言环境是英语,则必须使用path \Processor(_Total)\% Processor Time。
如果您的系统语言环境不是英语或意大利语,则必须使用PdhBrowseCounters函数自行查找路径。
以下非常基本的功能用法需要PdhMsg单位。
另请参阅MSDN 浏览性能计数器以获取更多参考。
function CounterPathCallBack(dwArg: DWORD_PTR): Longint; stdcall;
begin
Form1.Memo1.Lines.Add(PChar(dwArg));
Result := ERROR_SUCCESS;
end;
procedure TForm1.Button2Click(Sender: TObject);
const
PDH_MAX_COUNTER_PATH = 255;//maybe ?
BROWSE_DIALOG_CAPTION: PChar = 'Select a counter to monitor.';
var
browseDlgData: TPdhBrowseDlgConfig;
counterPathBuffer: array [0..PDH_MAX_COUNTER_PATH-1] of Char;
status: LongInt;
begin
FillChar(browseDlgData, SizeOf(TPdhBrowseDlgConfig), 0);
with browseDlgData do begin
{bIncludeInstanceIndex = FALSE;
bSingleCounterPerAdd = TRUE;
bSingleCounterPerDialog = TRUE;
bLocalCountersOnly = FALSE;
bWildCardInstances = TRUE;
bHideDetailBox = TRUE;
bInitializePath = FALSE;
bDisableMachineSelection = FALSE;
bIncludeCostlyObjects = FALSE;
bShowObjectBrowser = FALSE;}
hWndOwner := Self.Handle;
szReturnPathBuffer := @counterPathBuffer[0];
cchReturnPathLength := PDH_MAX_COUNTER_PATH;
pCallBack := CounterPathCallBack;
dwCallBackArg := DWORD_PTR(@counterPathBuffer[0]);
CallBackStatus := ERROR_SUCCESS;
dwDefaultDetailLevel := PERF_DETAIL_WIZARD;
szDialogBoxCaption := BROWSE_DIALOG_CAPTION;
end;
status := PdhBrowseCounters(browseDlgData);
case status of
PDH_DIALOG_CANCELLED, ERROR_SUCCESS:
;
else
RaiseLastOSError;
end;
end;
Run Code Online (Sandbox Code Playgroud)
Som*_*one -3
我找到了这个
做这份工作
uses adCpuUsage;
procedure TForm1.Button1Click(Sender: TObject);
var
i:integer;
u:string;
begin
collectcpudata;
for i:=0 to GetCPUCount-1 do
u:=FloatToStr(Round(getcpuusage(i)*100)); //Round to approximate 1.0003 to 1
label1.Caption:=u
end;
end.
Run Code Online (Sandbox Code Playgroud)