Delphi Gather CPU Information Within Your Windows App Using This Ultimate Component Suite

FireWind

Свой
Регистрация
2 Дек 2005
Сообщения
1,957
Реакции
1,199
Credits
4,009
Gather CPU Information Within Your Windows App Using This Ultimate Component Suite
February 15, 2021 By Anbarasan

Want to determine the manufacturer, speed of a CPU, CPU Type, CPU Physical Count, etc. from your Delphi application? Want to know the CPU Cache, Standard features, Extended features information from code ? Don’t know how to do. Don’t worry. Для просмотра ссылки Войди или Зарегистрируйся System Information Management Suite’s component helps to identify easily and we will learn how to use TMiTeC_CPU component in the blog post.

Platforms: Windows.

Installation Steps:

You can easily install this Component Suite from GetIt Package Manager. The steps are as follows.
  1. Navigate In RAD Studio IDE->Tools->GetIt Package Manager->select Components in Categories->Components->Trail -MiTec system Information Component Suite 14.3 and click Install Button.
  2. Read the license and Click Agree All. An Information dialog saying ‘Requires a restart of RAD studio at the end of the process. Do you want to proceed? click yes and continue.
  3. It will download the plugin and installs it. Once installed Click Restart now.
How to run the Demo app:
  • Navigate to the System Information Management Suite trails setup, Demos folder which is installed during Get It installation e.g) C:UsersDocumentsEmbarcaderoStudio21.0CatalogRepositoryMiTeC-14.3DemosDelphi14
  • Open the CPUTest project in RAD studio 10.4.1 compile and Run the application.
  • This Demo App shows how to gather some of the complex CPU information and its features.
1613369636663.png
Components used in MSIC CPUTest Demo App:
  • TMiTeC_CPU: Gathers complex information about CPU and its caches. Some of the Key properties were shown here.
  • TMemo: To list down the CPU information and its features.
  • TButton to run CPU test and close the app.
  • TCheckBox to save the CPU information in different file format such as XML,SIF file.
Implementation Details:
  • An instance CPU of TMiTeC_CPU is created. With CPU General properties values such as Number of Physical, logical, cores, threads, number of cores per package, etc. were retrieved.
  • By looping through the CPUPhysicalCount some of the processor properties values such as Architecture, Type, Vendor, CPU Name, etc. were retrieved. Cache and its properties, Logical Processor information were shown.
  • All these information were save to different file format based on the check boxes selected.
 

FireWind

Свой
Регистрация
2 Дек 2005
Сообщения
1,957
Реакции
1,199
Credits
4,009
Код:
procedure Twnd_cputest_Main.DetectCPU;
var
   i,j,m: Integer;
   s,f,fn: string;
   wmiServices: ISWbemServices;
   wmi: TInstances;
   CPUID: TCPUIDResult;
   CPU: TMiTeC_CPU;
   sl: TStringList;
   slpi: array of TSystemLogicalProcessorInformation;
   slpiex: array of TSystemLogicalProcessorInformationEx;
   n,c: Cardinal;
   h: Boolean;
begin
  with Box, Lines do begin
    Add('[CPU Test]');
    Add(Format('Version = %s',[cVersion]));
    {$IFDEF WIN32}
    Add('Target platform: 32-bit');
    {$ENDIF}
    {$IFDEF WIN64}
    Add('Target platform: 64-bit');
    {$ENDIF}
    Add('OS: '+FormOSName);
    Add('Machine: '+MachineName);
    Add('');
    CPU:=TMiTeC_CPU.Create(Self);
    with CPU do
      try
        Refreshdata;
        Add('[General]');
        Add(Format('Number of Physical Processors = %d',[CPUPhysicalCount]));
        Add(Format('Number of Logical Processors = %d',[CPUCount]));
        Add(Format('Total Number of Cores = %d',[CoreCount]));
        Add(Format('Total Number of Threads = %d',[ThreadCount]));
 
        Add(Format('Number of Cores per Package = %d',[CorePerPackage]));
        Add(Format('Number of Threads per Core = %d',[LogicalPerCore]));
        Add(Format('Number of Threads per Package = %d',[LogicalPerPackage]));
 
        Add(Format('Max number of Threads per Core = %d',[MaxLogicalPerCore]));
        Add(Format('Max number of Cores per Package = %d',[MaxCorePerPackage]));
        Add(Format('Max number of Threads per Package = %d',[MaxLogicalPerPackage]));
        Add('');
        c:=CPUPhysicalCount;
        for i:=0 to c-1 do begin
          CPUIndex:=i;
          Refreshdata;
          Add(Format('[Processor #%d]',[i+1]));
          case Architecture of
            PROCESSOR_ARCHITECTURE_AMD64: Add('Architecture = x64 (AMD or Intel)');
            PROCESSOR_ARCHITECTURE_IA32_ON_WIN64: Add('Architecture = WOW64');
            PROCESSOR_ARCHITECTURE_IA64: Add('Architecture = Intel Itanium Processor Family (IPF)');
            PROCESSOR_ARCHITECTURE_INTEL: Add('Architecture = x86');
            else Add(Format('Architecture = %d',[Architecture]));
          end;
          Add(Format('Type = %d',[SystemInfo.dwProcessorType]));
          Add(Format('Level = %d',[SystemInfo.wProcessorLevel]));
          Add(Format('Revision = %d (%4.4x)',[SystemInfo.wProcessorRevision,SystemInfo.wProcessorRevision]));
          Add(Format('APIC ID = %d',[APICID]));
          Add(Format('LogicalPerPackage = %d',[LogicalPerPackage]));
          Add(Format('CorePerPackage = %d',[CorePerPackage]));
          Add(Format('LogicalPerCore = %d',[LogicalPerCore]));
          Add(Format('Physical ID = %d',[PhysicalID]));
          Add(Format('Logical ID = %d',[LogicalID]));
          Add(Format('Vendor = %s',[cVendorNames[Vendor].Name]));
          Add(Format('CPUName = %s',[CPUName]));
          Add(Format('GenericName = %s',[GenericName]));
          Add(Format('MarketingName = %s',[MarketingName]));
          Add(Format('CodeName = %s',[CodeName]));
          Add(Format('Revision = %s',[Revision]));
          Add(Format('Technology = %s',[Technology]));
          Add(Format('Brand = %d',[Brand]));
          Add(Format('Type = %d',[CPUType]));
          Add(Format('FamilyEx = %d',[FamilyEx]));
          Add(Format('ModelEx = %d',[ModelEx]));
          Add(Format('SteppingEx = %d',[SteppingEx]));
          Add(Format('Frequency = %d MHz',[Frequency]));
          Add(Format('Serial Number = %s',[SerialNumber]));
          Add('');
          f:=GenericName;
          Add(Format('[CPUID #%d]',[i+1]));
          CPUID:=ExecuteCPUID(i,CPUID_STD_MaximumLevel);
          m:=CPUID.EAX;
          for j:=0 to m do begin
            CPUID:=ExecuteCPUID(-1,j);
            with CPUID do
              Add(Format('%8.8x = EAX:%8.8x  EBX:%8.8x  ECX:%8.8x  EDX:%8.8x',[CPUIDCommand,EAX,EBX,ECX,EDX]));
            if j=11 then begin
              CPUID:=ExecuteCPUID(-1,j,1,1);
              with CPUID do
                Add(Format('%8.8x = EAX:%8.8x  EBX:%8.8x  ECX:%8.8x  EDX:%8.8x',[CPUIDCommand,EAX,EBX,ECX,EDX]));
              CPUID:=ExecuteCPUID(-1,j,1,2);
              with CPUID do
                Add(Format('%8.8x = EAX:%8.8x  EBX:%8.8x  ECX:%8.8x  EDX:%8.8x',[CPUIDCommand,EAX,EBX,ECX,EDX]));
            end; 
          end;
 
          Add('');
 
          CPUID:=ExecuteCPUID(i,CPUID_EXT_MaximumLevel);
          m:=CPUID.EAX-CPUID_EXT_MaximumLevel;
          for j:=0 to m do begin
            CPUID:=ExecuteCPUID(i,j+CPUID_EXT_MaximumLevel);
            with CPUID do
              Add(Format('%8.8x = EAX:%8.8x  EBX:%8.8x  ECX:%8.8x  EDX:%8.8x',[CPUIDCommand,EAX,EBX,ECX,EDX]));
          end;
 
           with Cache.Level3 do begin
            if Typ>0 then
              Add(Format('%d x %s',[SharedWays,Descriptor]));
          end;
          with Cache.Trace do begin
            if Typ>0 then
              Add(Descriptor);
          end;
 
          Add('');
          s:='';
          if Vendor=cvIntel then begin
            with Cache.Level1.Code do
              for j:=1 to 16 do
                s:=s+Format('%2.2x ',[Descriptors[j]]);
            Add(Format('Level1 Descriptors = %s',[s]));
          end;
          s:='';
          with Cache.Level2 do begin
            if Vendor=cvIntel then begin
              for j:=1 to 16 do
                s:=s+Format('%2.2x ',[Descriptors[j]]);
              Add(Format('Level2 Descriptors = %s',[s]));
            end;
          end;
          s:='';
          with Cache.Level3 do begin
            if Vendor=cvIntel then begin
              for j:=1 to 16 do
                s:=s+Format('%2.2x ',[Descriptors[j]]);
              Add(Format('Level3 Descriptors = %s',[s]));
            end;
          end;
          s:='';
          with Cache.Trace do begin
            if Vendor=cvIntel then begin
              for j:=1 to 16 do
                s:=s+Format('%2.2x ',[Descriptors[j]]);
              Add(Format('Trace Descriptors = %s',[s]));
            end;
          end;
          Add('');
          Add(Format('[Standard Features #%d]',[i+1]));
          for j:=0 to Features.Standard.Count-1 do
            with Features.Standard.Features[j],Definition do
              Add(Format('%s (%s) = %d',[Name,Desc,Integer(Value)]));
          Add('');
          Add(Format('[Extended Features #%d]',[i+1]));
          for j:=0 to Features.Extended.Count-1 do
            with Features.Extended.Features[j],Definition do
              Add(Format('%s (%s) = %d',[Name,Desc,Integer(Value)]));
          Add('');
          Add(Format('[Power Management Features #%d]',[i+1]));
          for j:=0 to Features.PowerManagement.Count-1 do
            with Features.PowerManagement.Features[j],Definition do
              Add(Format('%s (%s) = %d',[Name,Desc,Integer(Value)]));
          Add('');
          Add(Format('[Secure Virtual Machine #%d]',[i+1]));
          for j:=0 to Features.SecureVirtualMachine.Count-1 do
            with Features.SecureVirtualMachine.Features[j],Definition do
              Add(Format('%s (%s) = %d',[Name,Desc,Integer(Value)]));
          Add('');
        end;
 
        Add('[Logical Processor Information]');
        n:=0;
        SetLength(slpi,1);
        if not GetLogicalProcessorInformation(@slpi[0],n) then begin
          if GetLastError=ERROR_INSUFFICIENT_BUFFER then begin
            SetLength(slpi,n div SizeOf(TSystemLogicalProcessorInformation)+1);
            if GetLogicalProcessorInformation(@slpi[0],n) then begin
              for i:=0 to High(slpi) do
                case slpi[i].Relationship of
                  RelationProcessorCore: Add(Format('[%d] RelationProcessorCore: %d bits set',[i,CountSetBits(slpi[i].ProcessorMask)]));
                  RelationProcessorPackage: Add(Format('[%d] RelationProcessorPackage',[i]));
                  RelationNumaNode: Add(Format('[%d] RelationNumaNode',[i]));
                  RelationCache: with slpi[i].Cache do Add(Format('[%d] RelationCache: Type=%d, Level=%d, Associativity=%d, LineSize=%d, Size=%d',[i,Integer(_Type),Level,Associativity,LineSize,Size]));
                  RelationGroup: Add(Format('[%d] RelationGroup',[i]));
                  else Add(Format('[%d] (out of range): %d',[i,Integer(slpi[i].Relationship)]));
                end;
            end else
              Add('Not available');
          end else
            Add('Not available');
        end else
          Add('Not available');
 
        Add('');
        Add('[Logical Processor Information Ex]');
        n:=0;
        SetLength(slpiex,1);
        GetLogicalProcessorInformationEx(RelationAll,nil,n);
        SetLength(slpiex,n div SizeOf(TSystemLogicalProcessorInformationEx)+1);
        if GetLogicalProcessorInformationEx(RelationAll,@slpiex[0],n) then begin
          for i:=0 to High(slpiex) do
            case slpiex[i].Relationship of
              RelationProcessorCore: Add(Format('[%d] RelationProcessorCore',[i]));
              RelationProcessorPackage: Add(Format('[%d] RelationProcessorPackage: %d',[i,slpiex[i].Processor.Flags]));
              RelationNumaNode: Add(Format('[%d] RelationNumaNode: %d',[i,slpiex[i].NumaNode.NodeNumber]));
              RelationCache: with slpiex[i].Cache do Add(Format('[%d] RelationCache: Type=%d, Level=%d, Associativity=%d, LineSize=%d, Size=%d',[i,Integer(_Type),Level,Associativity,LineSize,CacheSize]));
              RelationGroup: Add(Format('[%d] RelationGroup',[i]));
              else Add(Format('[%d] (out of range): %d',[i,Integer(slpiex[i].Relationship)]));
            end;
        end else
          Add('Not available');
        
        fn:=f+'.sif';
        h:=True;
        if cbxSave.Checked then
          SaveToStorage(ExtractFilePath(Application.EXEName)+fn,h);
      finally
        Free;
      end;
 
      if cbxSMBIOS.Checked then begin
        Add('');
        Add('[SMBIOS]');
        with TMiTeC_SMBIOS.Create(Self) do
          try
            Refreshdata;
            for i:=0 to ProcessorCount-1 do begin
              Add(Format('Vendor[%d] = %s',[i,Processor[i].Manufacturer]));
              Add(Format('NameString[%d] = %s',[i,Processor[i].Version]));
              Add(Format('Socket[%d] = %s',[i,Processor[i].Socket+'('+Upgrades[Processor[i].Upgrade]+')']));
              Add(Format('Voltage[%d] = %1.1f V',[i,Processor[i].Voltage]));
              Add(Format('Frequency[%d] = %d MHz',[i,Processor[i].Frequency]));
              Add(Format('ExternalClock[%d] = %d MHz',[i,Processor[i].ExternalClock]));
            end;
            for i:=0 to CacheCount-1 do
              Add(Format('%s = %d of %d KB - %d ns (%s,%s,%s)',[Cache[i].Designation,
                                                                     Cache[i].InstalledSize,
                                                                     Cache[i].MaxSize,
                                                                     Cache[i].Speed,
                                                                     CacheTypes[Cache[i].Typ],
                                                                     CacheAssociativities[Cache[i].Associativity],
                                                                     SRAMTypes[Cache[i].SRAMType]]));
 
 
          h:=True;
          if cbxSave.Checked then
            SaveToStorage(ExtractFilePath(Application.EXEName)+fn,h);
        finally
          Free;
        end;
      end;
 
      if cbxWMI.Checked then begin
        Add('');
        Add('[WMI]');
        try
          if not WMIConnect('','','',Rootnamespace,wmiServices) then
            Exit;
          WMICommand(wmiServices,'Win32_Processor',wmi);
 
          for i:=0 to High(wmi) do
            for j:=0 to High(wmi[i]) do
              Add(Format('%s[%d] = %s',[wmi[i][j].Name,i,wmi[i][j].Value]));
 
          if cbxSave.Checked then
            WmiSaveToStorage('Win32_Processor',ExtractFilePath(Application.EXEName)+fn,wmi);
        finally
          WMIDisconnect(wmiServices);
          Finalize(wmi);
        end;
      end;
 
      Add('');
 
      Add('Test passed.');
      fn:=Format('%s.txt',[f]);
 
    try
      SaveToFile(ExtractFilePath(Application.EXEName)+fn);
    except
    end;
  end;
  Box.SelStart:=0;
  Box.SelLength:=0;
end;
1613369873802.png
MiTeC CPUTest Demo

This is quite easy to collect CPU information from your application. Use this MiTeC component suite and get the job done quickly.
Head over and check out the full MiTec System Information Management Suite for Access System Information for Windows in Delphi Applications