获取 CPU 使用率的单元

 
  1. unit UnitCPU;
  2. interface
  3. uses
  4. Windows, SysUtils;
  5. // Call CollectCPUData to refresh information about CPU usage
  6. procedure CollectCPUData;
  7. // Call it to obtain the number of CPU's in the system
  8. function GetCPUCount: integer;
  9. // Call it to obtain the % of usage for given CPU
  10. function GetCPUUsage(Index: integer): double;
  11. // For Win9x only: call it to stop CPU usage monitoring and free system resources
  12. procedure ReleaseCPUData;
  13. implementation
  14. type
  15. PInt64 = ^TInt64;
  16. TInt64 = int64;
  17. type
  18. TPERF_DATA_BLOCK = record
  19.     Signature:        array[0..4 - 1of WCHAR;
  20.     LittleEndian:     DWORD;
  21.     Version:          DWORD;
  22.     Revision:         DWORD;
  23.     TotalByteLength: DWORD;
  24.     HeaderLength:     DWORD;
  25.     NumObjectTypes:   DWORD;
  26.     DefaultObject:    longint;
  27.     SystemTime:       TSystemTime;
  28.     Reserved:         DWORD;
  29.     PerfTime:         TInt64;
  30.     PerfFreq:         TInt64;
  31.     PerfTime100nSec: TInt64;
  32.     SystemNameLength: DWORD;
  33.     SystemNameOffset: DWORD;
  34. end;
  35. PPERF_DATA_BLOCK = ^TPERF_DATA_BLOCK;
  36. TPERF_OBJECT_TYPE = record
  37.     TotalByteLength: DWORD;
  38.     DefinitionLength: DWORD;
  39.     HeaderLength: DWORD;
  40.     ObjectNameTitleIndex: DWORD;
  41.     ObjectNameTitle: LPWSTR;
  42.     ObjectHelpTitleIndex: DWORD;
  43.     ObjectHelpTitle: LPWSTR;
  44.     DetailLevel: DWORD;
  45.     NumCounters: DWORD;
  46.     DefaultCounter: longint;
  47.     NumInstances: longint;
  48.     CodePage: DWORD;
  49.     PerfTime: TInt64;
  50.     PerfFreq: TInt64;
  51. end;
  52. PPERF_OBJECT_TYPE = ^TPERF_OBJECT_TYPE;
  53. type
  54. TPERF_COUNTER_DEFINITION = record
  55.     ByteLength:       DWORD;
  56.     CounterNameTitleIndex: DWORD;
  57.     CounterNameTitle: LPWSTR;
  58.     CounterHelpTitleIndex: DWORD;
  59.     CounterHelpTitle: LPWSTR;
  60.     DefaultScale:     longint;
  61.     DetailLevel:      DWORD;
  62.     CounterType:      DWORD;
  63.     CounterSize:      DWORD;
  64.     CounterOffset:    DWORD;
  65. end;
  66. PPERF_COUNTER_DEFINITION = ^TPERF_COUNTER_DEFINITION;
  67. TPERF_COUNTER_BLOCK = record
  68.     ByteLength: DWORD;
  69. end;
  70. PPERF_COUNTER_BLOCK = ^TPERF_COUNTER_BLOCK;
  71. TPERF_INSTANCE_DEFINITION = record
  72.     ByteLength: DWORD;
  73.     ParentObjectTitleIndex: DWORD;
  74.     ParentObjectInstance: DWORD;
  75.     UniqueID:   longint;
  76.     NameOffset: DWORD;
  77.     NameLength: DWORD;
  78. end;
  79. PPERF_INSTANCE_DEFINITION = ^TPERF_INSTANCE_DEFINITION;
  80. type
  81. TInt64F = TInt64;
  82. type
  83. FInt64 = TInt64F;
  84. Int64D = TInt64;
  85. //------------------------------------------------------------------------------
  86. const
  87. Processor_IDX_Str = '238';
  88. Processor_IDX     = 238;
  89. CPUUsageIDX       = 6;
  90. type
  91. AInt64F = array[0..$FFFFof TInt64F;
  92. PAInt64F = ^AInt64F;
  93. var
  94. _PerfData:      PPERF_DATA_BLOCK;
  95. _BufferSize:    integer;
  96. _POT:           PPERF_OBJECT_TYPE;
  97. _PCD:           PPerf_Counter_Definition;
  98. _ProcessorsCount: integer;
  99. _Counters:      PAInt64F;
  100. _PrevCounters: PAInt64F;
  101. _SysTime:       TInt64F;
  102. _PrevSysTime:   TInt64F;
  103. _IsWinNT:       boolean;
  104. _W9xCollecting: boolean;
  105. _W9xCpuUsage:   DWORD;
  106. _W9xCpuKey:     HKEY;
  107. //------------------------------------------------------------------------------
  108. function GetCPUCount: integer;
  109. begin
  110. if _IsWinNT then
  111. begin
  112.     if _ProcessorsCount < 0 then
  113.       CollectCPUData;
  114.     Result := _ProcessorsCount;
  115. end else
  116. begin
  117.     Result := 1;
  118. end;
  119. end;
  120. //------------------------------------------------------------------------------
  121. procedure ReleaseCPUData;
  122. var
  123. H: HKEY;
  124. R: DWORD;
  125. dwDataSize, dwType: DWORD;
  126. begin
  127. if _IsWinNT then
  128.     exit;
  129. if not _W9xCollecting then
  130.     exit;
  131. _W9xCollecting := False;
  132. RegCloseKey(_W9xCpuKey);
  133. R := RegOpenKeyEx(HKEY_DYN_DATA, 'PerfStats/StopStat'0, KEY_ALL_ACCESS, H);
  134. if R <> ERROR_SUCCESS then
  135.     exit;
  136. dwDataSize := sizeof(DWORD);
  137. RegQueryValueEx(H, 'KERNEL/CPUUsage'nil, @dwType, PBYTE(@_W9xCpuUsage),
  138.     @dwDataSize);
  139. RegCloseKey(H);
  140. end;
  141. //------------------------------------------------------------------------------
  142. function GetCPUUsage(Index: integer): double;
  143. begin
  144. if _IsWinNT then
  145. begin
  146.     if _ProcessorsCount < 0 then
  147.       CollectCPUData;
  148.     if (Index >= _ProcessorsCount) or (Index < 0then
  149.       raise Exception.Create('CPU index out of bounds');
  150.     if _PrevSysTime = _SysTime then
  151.       Result := 0
  152.     else
  153.       Result := 1 - (_Counters[index] - _PrevCounters[index]) / (_SysTime - _PrevSysTime);
  154. end else
  155. begin
  156.     if Index <> 0 then
  157.       raise Exception.Create('CPU index out of bounds');
  158.     if not _W9xCollecting then
  159.       CollectCPUData;
  160.     Result := _W9xCpuUsage / 100;
  161. end;
  162. end;
  163. var
  164. VI: TOSVERSIONINFO;
  165. //------------------------------------------------------------------------------
  166. procedure CollectCPUData;
  167. var
  168. BS: integer;
  169. i: integer;
  170. _PCB_Instance: PPERF_COUNTER_BLOCK;
  171. _PID_Instance: PPERF_INSTANCE_DEFINITION;
  172. ST: TFileTime;
  173. var
  174. H: HKEY;
  175. R: DWORD;
  176. dwDataSize, dwType: DWORD;
  177. begin
  178. if _IsWinNT then
  179. begin
  180.     BS := _BufferSize;
  181.     while RegQueryValueEx(HKEY_PERFORMANCE_DATA, Processor_IDX_Str,
  182.         nilnil, PByte(_PerfData), @BS) = ERROR_MORE_DATA do
  183.     begin
  184.       // Get a buffer that is big enough.
  185.       Inc(_BufferSize, $1000);
  186.       BS := _BufferSize;
  187.       ReallocMem(_PerfData, _BufferSize);
  188.     end;
  189.     // Locate the performance object
  190.     _POT := PPERF_OBJECT_TYPE(DWORD(_PerfData) + _PerfData.HeaderLength);
  191.     for i := 1 to _PerfData.NumObjectTypes do
  192.     begin
  193.       if _POT.ObjectNameTitleIndex = Processor_IDX then
  194.         Break;
  195.       _POT := PPERF_OBJECT_TYPE(DWORD(_POT) + _POT.TotalByteLength);
  196.     end;
  197.     // Check for success
  198.     if _POT.ObjectNameTitleIndex <> Processor_IDX then
  199.       raise Exception.Create(
  200.         'Unable to locate the "Processor" performance object');
  201.     if _ProcessorsCount < 0 then
  202.     begin
  203.       _ProcessorsCount := _POT.NumInstances;
  204.       GetMem(_Counters, _ProcessorsCount * SizeOf(TInt64));
  205.       GetMem(_PrevCounters, _ProcessorsCount * SizeOf(TInt64));
  206.     end;
  207.     // Locate the "% CPU usage" counter definition
  208.     _PCD := PPERF_Counter_DEFINITION(DWORD(_POT) + _POT.HeaderLength);
  209.     for i := 1 to _POT.NumCounters do
  210.     begin
  211.       if _PCD.CounterNameTitleIndex = CPUUsageIDX then
  212.         break;
  213.       _PCD := PPERF_COUNTER_DEFINITION(DWORD(_PCD) + _PCD.ByteLength);
  214.     end;
  215.     // Check for success
  216.     if _PCD.CounterNameTitleIndex <> CPUUsageIDX then
  217.       raise Exception.Create(
  218.         'Unable to locate the "% of CPU usage" performance counter');
  219.     // Collecting coutners
  220.     _PID_Instance := PPERF_INSTANCE_DEFINITION(DWORD(_POT) + _POT.DefinitionLength);
  221.     for i := 0 to _ProcessorsCount - 1 do
  222.     begin
  223.       _PCB_Instance    := PPERF_COUNTER_BLOCK(DWORD(_PID_Instance) +
  224.         _PID_Instance.ByteLength);
  225.       _PrevCounters[i] := _Counters[i];
  226.       _Counters[i]     := FInt64(PInt64(DWORD(_PCB_Instance) + _PCD.CounterOffset)^);
  227.       _PID_Instance    := PPERF_INSTANCE_DEFINITION(DWORD(_PCB_Instance) +
  228.         _PCB_Instance.ByteLength);
  229.     end;
  230.     _PrevSysTime := _SysTime;
  231.     SystemTimeToFileTime(_PerfData.SystemTime, ST);
  232.     _SysTime := FInt64(TInt64(ST));
  233. end else
  234. begin
  235.     if not _W9xCollecting then
  236.     begin
  237.       R := RegOpenKeyEx(HKEY_DYN_DATA, 'PerfStats/StartStat',
  238.         0, KEY_ALL_ACCESS, H);
  239.       if R <> ERROR_SUCCESS then
  240.         raise Exception.Create('Unable to start performance monitoring');
  241.       dwDataSize := sizeof(DWORD);
  242.       RegQueryValueEx(H, 'KERNEL/CPUUsage'nil, @dwType,
  243.         PBYTE(@_W9xCpuUsage), @dwDataSize);
  244.       RegCloseKey(H);
  245.       R := RegOpenKeyEx(HKEY_DYN_DATA, 'PerfStats/StatData',
  246.         0, KEY_READ, _W9xCpuKey);
  247.       if R <> ERROR_SUCCESS then
  248.         raise Exception.Create('Unable to read performance data');
  249.       _W9xCollecting := True;
  250.     end;
  251.     dwDataSize := sizeof(DWORD);
  252.     RegQueryValueEx(_W9xCpuKey, 'KERNEL/CPUUsage'nil, @dwType,
  253.       PBYTE(@_W9xCpuUsage), @dwDataSize);
  254. end;
  255. end;
  256. initialization
  257. _ProcessorsCount := -1;
  258. _BufferSize      := $2000;
  259. _PerfData        := AllocMem(_BufferSize);
  260. VI.dwOSVersionInfoSize := SizeOf(VI);
  261. if not GetVersionEx(VI) then
  262.     raise Exception.Create('Can''t get the Windows version');
  263. _IsWinNT := VI.dwPlatformId = VER_PLATFORM_WIN32_NT;
  264. finalization
  265. ReleaseCPUData;
  266. FreeMem(_PerfData);
  267. end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值