在此附上adCpuUsage.pas源代码,请有条件的帮我分析一下问题出在哪里,不胜感激。<br><br>unit adCpuUsage;<br>{*<br>USAGE:<br><br>1. Include this unit into project.<br><br>2. Call GetCPUCount to obtain the numbr of processors in the system<br><br>3. Each time you need to know the value of CPU usage call the CollectCPUData<br> to refresh the CPU usage information. Then call the GetCPUUsage to obtain<br> the CPU usage for given processor. Note that succesive calls of GetCPUUsage<br> without calling CollectCPUData will return the same CPU usage value.<br><br>Example:<br><br>procedure TTestForm.TimerTimer(Sender: TObject);<br>var i: Integer;<br>begin<br> CollectCPUData; // Get the data for all processors<br><br> for i:=0 to GetCPUCount-1 do // Show data for each processor<br> MInfo.Lines:=Format('CPU #%d - %5.2f%%',[i,GetCPUUsage(i)*100]);<br>end;<br>*}<br><br>interface<br><br>uses<br> Windows, SysUtils;<br><br>// Call CollectCPUData to refresh information about CPU usage<br>procedure CollectCPUData;<br><br>// Call it to obtain the number of CPU's in the system<br>function _GetCPUCount: Integer;<br><br>// Call it to obtain the % of usage for given CPU<br>function _GetCPUUsage(Index: Integer): Double;<br><br>// For Win9x only: call it to stop CPU usage monitoring and free system resources<br>procedure ReleaseCPUData;<br><br>implementation<br><br>{$ifndef ver110}<br><br> {$ifndef ver90}<br> {$ifndef ver100}<br> {$define UseInt64}<br> {$endif}<br> {$endif}<br><br><br> {$ifdef UseInt64}<br> type TInt64 = Int64;<br> {$else}<br> type TInt64 = Comp;<br> {$endif}<br><br>{$else}<br><br> type TInt64 = TLargeInteger;<br><br>{$endif}<br><br>type<br> PInt64 = ^TInt64;<br><br>type<br> TPERF_DATA_BLOCK = record<br> Signature : array[0..4 - 1] of WCHAR;<br> LittleEndian : DWORD;<br> Version : DWORD;<br> Revision : DWORD;<br> TotalByteLength : DWORD;<br> HeaderLength : DWORD;<br> NumObjectTypes : DWORD;<br> DefaultObject : Longint;<br> SystemTime : TSystemTime;<br> Reserved: DWORD;<br> PerfTime : TInt64;<br> PerfFreq : TInt64;<br> PerfTime100nSec : TInt64;<br> SystemNameLength : DWORD;<br> SystemNameOffset : DWORD;<br> end;<br><br> PPERF_DATA_BLOCK = ^TPERF_DATA_BLOCK;<br><br> TPERF_OBJECT_TYPE = record<br> TotalByteLength : DWORD;<br> DefinitionLength : DWORD;<br> HeaderLength : DWORD;<br> ObjectNameTitleIndex : DWORD;<br> ObjectNameTitle : LPWSTR;<br> ObjectHelpTitleIndex : DWORD;<br> ObjectHelpTitle : LPWSTR;<br> DetailLevel : DWORD;<br> NumCounters : DWORD;<br> DefaultCounter : Longint;<br> NumInstances : Longint;<br> CodePage : DWORD;<br> PerfTime : TInt64;<br> PerfFreq : TInt64;<br> end;<br><br> PPERF_OBJECT_TYPE = ^TPERF_OBJECT_TYPE;<br><br>type<br> TPERF_COUNTER_DEFINITION = record<br> ByteLength : DWORD;<br> CounterNameTitleIndex : DWORD;<br> CounterNameTitle : LPWSTR;<br> CounterHelpTitleIndex : DWORD;<br> CounterHelpTitle : LPWSTR;<br> DefaultScale : Longint;<br> DetailLevel : DWORD;<br> CounterType : DWORD;<br> CounterSize : DWORD;<br> CounterOffset : DWORD;<br> end;<br><br> PPERF_COUNTER_DEFINITION = ^TPERF_COUNTER_DEFINITION;<br><br> TPERF_COUNTER_BLOCK = record<br> ByteLength : DWORD;<br> end;<br><br> PPERF_COUNTER_BLOCK = ^TPERF_COUNTER_BLOCK;<br><br> TPERF_INSTANCE_DEFINITION = record<br> ByteLength : DWORD;<br> ParentObjectTitleIndex : DWORD;<br> ParentObjectInstance : DWORD;<br> UniqueID : Longint;<br> NameOffset : DWORD;<br> NameLength : DWORD;<br> end;<br><br> PPERF_INSTANCE_DEFINITION = ^TPERF_INSTANCE_DEFINITION;<br><br>//------------------------------------------------------------------------------<br>{$ifdef ver130}<br>{$L-} // The L+ causes internal error in Delphi 5 compiler<br>{$O-} // The O+ causes internal error in Delphi 5 compiler<br>{$Y-} // The Y+ causes internal error in Delphi 5 compiler<br>{$endif}<br><br>{$ifndef ver110}<br>type<br> TInt64F = TInt64;<br>{$else}<br>type<br> TInt64F = Extended;<br>{$endif}<br><br>{$ifdef ver110}<br>function FInt64(Value: TInt64): TInt64F;<br>function Int64D(Value: DWORD): TInt64;<br>{$else}<br>type<br> FInt64 = TInt64F;<br> Int64D = TInt64;<br>{$endif}<br><br>{$ifdef ver110}<br>function FInt64(Value: TInt64): TInt64F;<br>var V: TInt64;<br>begin<br> if (Value.HighPart and $80000000) = 0 then // positive value<br> begin<br> result:=Value.HighPart;<br> result:=result*$10000*$10000;<br> result:=result+Value.LowPart;<br> end else<br> begin<br> V.HighPart:=Value.HighPart xor $FFFFFFFF;<br> V.LowPart:=Value.LowPart xor $FFFFFFFF;<br> result:= -1 - FInt64(V);<br> end;<br>end;<br><br>function Int64D(Value: DWORD): TInt64;<br>begin<br> result.LowPart:=Value;<br> result.HighPart := 0; // positive only<br>end;<br>{$endif}<br><br>//------------------------------------------------------------------------------<br><br>const<br> Processor_IDX_Str = '238';<br> Processor_IDX = 238;<br> CPUUsageIDX = 6;<br><br>type<br> AInt64F = array[0..$FFFF] of TInt64F;<br> PAInt64F = ^AInt64F;<br><br>var<br> _PerfData : PPERF_DATA_BLOCK;<br> _BufferSize: Integer;<br> _POT : PPERF_OBJECT_TYPE;<br> _PCD: PPerf_Counter_Definition;<br> _ProcessorsCount: Integer;<br> _Counters: PAInt64F;<br> _PrevCounters: PAInt64F;<br> _SysTime: TInt64F;<br> _PrevSysTime: TInt64F;<br> _IsWinNT: Boolean;<br><br> _W9xCollecting: Boolean;<br> _W9xCpuUsage: DWORD;<br> _W9xCpuKey: HKEY;<br><br><br>//------------------------------------------------------------------------------<br>function _GetCPUCount: Integer;<br>begin<br> if _IsWinNT then<br> begin<br> if _ProcessorsCount < 0 then CollectCPUData;<br> result:=_ProcessorsCount;<br> end else<br> begin<br> result:=1;<br> end;<br><br>end;<br><br>//------------------------------------------------------------------------------<br>procedure ReleaseCPUData;<br>var H: HKEY;<br> R: DWORD;<br> dwDataSize, dwType: DWORD;<br>begin<br> if _IsWinNT then exit;<br> if not _W9xCollecting then exit;<br> _W9xCollecting:=False;<br><br> RegCloseKey(_W9xCpuKey);<br><br> R:=RegOpenKeyEx( HKEY_DYN_DATA, 'PerfStats/StopStat', 0, KEY_ALL_ACCESS, H );<br><br> if R <> ERROR_SUCCESS then exit;<br><br> dwDataSize:=sizeof(DWORD);<br><br> RegQueryValueEx ( H, 'KERNEL/CPUUsage', nil, @dwType, PBYTE(@_W9xCpuUsage), @dwDataSize);<br><br> RegCloseKey(H);<br><br>end;<br><br>//------------------------------------------------------------------------------<br>function _GetCPUUsage(Index: Integer): Double;<br>begin<br> if _IsWinNT then<br> begin<br> if _ProcessorsCount < 0 then CollectCPUData;<br> if (Index >= _ProcessorsCount) or (Index < 0) then<br> raise Exception.Create('CPU index out of bounds');<br> if _PrevSysTime = _SysTime then result:=0 else<br> result:=1-(_Counters[index] - _PrevCounters[index])/(_SysTime-_PrevSysTime);<br> end else<br> begin<br> if Index <> 0 then<br> raise Exception.Create('CPU index out of bounds');<br> if not _W9xCollecting then CollectCPUData;<br> result:=_W9xCpuUsage / 100;<br> end;<br>end;<br><br>var VI: TOSVERSIONINFO;<br><br>//------------------------------------------------------------------------------<br>procedure CollectCPUData;<br>var BS: integer;<br> i: Integer;<br> _PCB_Instance: PPERF_COUNTER_BLOCK;<br> _PID_Instance: PPERF_INSTANCE_DEFINITION;<br> ST: TFileTime;<br><br>var H: HKEY;<br> R: DWORD;<br> dwDataSize, dwType: DWORD;<br>begin<br> if _IsWinNT then<br> begin<br> BS:=_BufferSize;<br> while RegQueryValueEx( HKEY_PERFORMANCE_DATA, Processor_IDX_Str, nil, nil,<br> PByte(_PerfData), @BS ) = ERROR_MORE_DATA do<br> begin<br> // Get a buffer that is big enough.<br> INC(_BufferSize,$1000);<br> BS:=_BufferSize;<br> ReallocMem( _PerfData, _BufferSize );<br> end;<br><br> // Locate the performance object<br> _POT := PPERF_OBJECT_TYPE(DWORD(_PerfData) + _PerfData.HeaderLength);<br> for i := 1 to _PerfData.NumObjectTypes do<br> begin<br> if _POT.ObjectNameTitleIndex = Processor_IDX then Break;<br> _POT := PPERF_OBJECT_TYPE(DWORD(_POT) + _POT.TotalByteLength);<br> end;<br><br> // Check for success<br> if _POT.ObjectNameTitleIndex <> Processor_IDX then<br> raise Exception.Create('Unable to locate the "Processor" performance object');<br><br> if _ProcessorsCount < 0 then<br> begin<br> _ProcessorsCount:=_POT.NumInstances;<br> GetMem(_Counters,_ProcessorsCount*SizeOf(TInt64));<br> GetMem(_PrevCounters,_ProcessorsCount*SizeOf(TInt64));<br> end;<br><br> // Locate the "% CPU usage" counter definition<br> _PCD := PPERF_Counter_DEFINITION(DWORD(_POT) + _POT.HeaderLength);<br> for i := 1 to _POT.NumCounters do<br> begin<br> if _PCD.CounterNameTitleIndex = CPUUsageIDX then break;<br> _PCD := PPERF_COUNTER_DEFINITION(DWORD(_PCD) + _PCD.ByteLength);<br> end;<br><br> // Check for success<br> if _PCD.CounterNameTitleIndex <> CPUUsageIDX then<br> raise Exception.Create('Unable to locate the "% of CPU usage" performance counter');<br><br> // Collecting coutners<br> _PID_Instance := PPERF_INSTANCE_DEFINITION(DWORD(_POT) + _POT.DefinitionLength);<br> for i := 0 to _ProcessorsCount-1 do<br> begin<br> _PCB_Instance := PPERF_COUNTER_BLOCK(DWORD(_PID_Instance) + _PID_Instance.ByteLength );<br><br> _PrevCounters:=_Counters;<br> _Counters:=FInt64(PInt64(DWORD(_PCB_Instance) + _PCD.CounterOffset)^);<br><br> _PID_Instance := PPERF_INSTANCE_DEFINITION(DWORD(_PCB_Instance) + _PCB_Instance.ByteLength);<br> end;<br><br> _PrevSysTime:=_SysTime;<br> SystemTimeToFileTime(_PerfData.SystemTime, ST);<br> _SysTime:=FInt64(TInt64(ST));<br> end else<br> begin<br> if not _W9xCollecting then<br> begin<br> R:=RegOpenKeyEx( HKEY_DYN_DATA, 'PerfStats/StartStat', 0, KEY_ALL_ACCESS, H );<br> if R <> ERROR_SUCCESS then<br> raise Exception.Create('Unable to start performance monitoring');<br><br> dwDataSize:=sizeof(DWORD);<br><br> RegQueryValueEx( H, 'KERNEL/CPUUsage', nil, @dwType, PBYTE(@_W9xCpuUsage), @dwDataSize );<br><br> RegCloseKey(H);<br><br> R:=RegOpenKeyEx( HKEY_DYN_DATA, 'PerfStats/StatData', 0,KEY_READ, _W9xCpuKey );<br><br> if R <> ERROR_SUCCESS then<br> raise Exception.Create('Unable to read performance data');<br><br> _W9xCollecting:=True;<br> end;<br><br> dwDataSize:=sizeof(DWORD);<br> RegQueryValueEx( _W9xCpuKey, 'KERNEL/CPUUsage', nil,@dwType, PBYTE(@_W9xCpuUsage), @dwDataSize );<br> end;<br>end;<br><br><br>initialization<br> _ProcessorsCount:= -1;<br> _BufferSize:= $2000;<br> _PerfData := AllocMem(_BufferSize);<br><br> VI.dwOSVersionInfoSize:=SizeOf(VI);<br> if not GetVersionEx(VI) then raise Exception.Create('Can''t get the Windows version');<br><br> _IsWinNT := VI.dwPlatformId = VER_PLATFORM_WIN32_NT;<br>finalization<br> ReleaseCPUData;<br> FreeMem(_PerfData);<br>end.