以下代码是从别人那看来的 但发觉我每次提取序列号似乎不同 请问是不是双核CPU造成的 如何纠正这个问题呢FUNCTION GetCPUID : TCPUID; assembler; register;
asm
  PUSH    EBX         {Save affected register}
  PUSH    EDI
  MOV     EDI,EAX     {@Resukt}
  MOV     EAX,1
  DW      $A20F       {CPUID Command}
  STOSD      {CPUID[1]}
  MOV     EAX,EBX
  STOSD               {CPUID[2]}
  MOV     EAX,ECX
  STOSD               {CPUID[3]}
  MOV     EAX,EDX
  STOSD               {CPUID[4]}
  POP     EDI      {Restore registers}
  POP     EBX
END;  function GetCPUSerialNumber: String;
var
  CPUID:TCPUID;
begin
  Result:='';
  CPUID:=GetCPUID; 
  Result := IntToHex(CPUID[1],8)+IntToHex(CPUID[2],8)+IntToHex(CPUID[3],8)+IntToHex(CPUID[4],8);
end;

解决方案 »

  1.   

    cnpack组件包中有获取CPU号的例子,你可以看下。
      

  2.   

    只有PentiumIII支持序列号,所以读取之前要先检测是否支持序列号,先设置eax=1执行cpuid,返回的edx位18(10进制)如果为1则支持。
      

  3.   

    PS:eax=3执行cpuid取序列号的低64位,PSN= eax=1返回的eax+ eax=3返回的edx:ecx。
      

  4.   


    {******************************************************************************}
    {                       CnPack For Delphi/C++Builder                           }
    {                     中国人自己的开放源码第三方开发包                         }
    {                   (C)Copyright 2001-2008 CnPack 开发组                       }
    {                   ------------------------------------                       }
    {                                                                              }
    {            本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修        }
    {        改和重新发布这一程序。                                                }
    {                                                                              }
    {            发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有        }
    {        适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。        }
    {                                                                              }
    {            您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果        }
    {        还没有,可访问我们的网站:                                            }
    {                                                                              }
    {            网站地址:http://www.cnpack.org                                   }
    {            电子邮件:[email protected]                                       }
    {                                                                              }
    {******************************************************************************}unit CnHardWareInfo;
    {* |<PRE>
    ================================================================================
    * 软件名称:CnPack 组件包
    * 单元名称:硬件信息单元
    * 单元作者:SkyJacker
    *           LiuXiao
    * 备    注:硬件信息单元,目前只实现获取多核、多CPU系统中指定CPU的序列号与占用率
    * 开发平台:WindowsXP sp2 + Delphi 6.0 up2
    * 兼容测试:Win2000/XP + Delphi 5、6
    * 本 地 化:该单元中的字符串均符合本地化处理方式
    * 单元标识:$Id: CnHardWareInfo.pas,v 1.4 2008/03/06 13:07:21 liuxiao Exp $
    * 修改记录:2008.01.12 V1.1
    *               LiuXiao 加入对 CPU 占用率的读取
    *           2007.01.23 V1.0
    *               创建单元,实现功能
    ================================================================================
    |</PRE>}interface{$I CnPack.inc}uses
      Classes, Windows, SysUtils, ExtCtrls;
      
    type
      TCnCPUIdFormat = (ifContinuous, ifDashed);
      {* CPU序列号显示样式
       |<PRE>
         ifContinuous:  -连续型
         ifDashed:      -使用分割符'-'分割
       |</PRE>
      }  TCnCpuId = class(TPersistent)
      {CPU 信息类}
      private
        FTimer: TTimer;
        FCPUCount: Integer;
        FCPUIds: TStrings;
        FCPUIdFormat: TCnCPUIdFormat;
        FCPUUsageRead: Boolean;
        FCPUUsage: array[0..255] of Integer; // 总不会超过 256 个 CPU 吧?
        FCurCnt, FLastCnt: array[0..255] of Integer;
        FAverageCPUUsage: Integer;
        function GetFirstCPUId: string;
        function GetCPUId(Index: Integer): string;
        procedure SetCPUIdFormat(ACPUIdFormat: TCnCPUIdFormat);
        function GetAverageCPUUsage: Integer;
        function GetCPUUsage(Index: Integer): Integer;
        function GetFirstCPUUsage: Integer;    function RefreshCPUUsages: Cardinal; // 只被定时调用
        procedure CpuUsageTimer(Sender: TObject);
      public
        constructor Create;
        {* 构造函数,创建 FCPUIds 并调用 ReadCPUId}
        destructor Destroy; override;    procedure ReadCPUId;
        {* 获得所有 CPU 内核的序列号,并存入 FCPUIds 列表}    property CPUIdFormat: TCnCPUIdFormat read FCPUIdFormat write SetCPUIdFormat;
        {* CPU 序列号显示样式}
        property CPUCount: Integer read FCPUCount;
        {* 系统中 CPU 核总数}
        property FirstCPUId: string read GetFirstCPUId;
        {* 获取首个 CPU 的 ID,用于单 CPU 系统}
        property CPUId[Index: Integer]: string read GetCPUId;
        {* 获得指定 CPU 的序列号。索引 Index 从 0 开始}
        property CPUUsage[Index: Integer]: Integer read GetCPUUsage;
        {* 获得指定 CPU 的占用率,0 到 100
           需要说明的是,本类在 NT 系统上采用定时采样获得 CPU 的忙周期数再计算而来,
           因此在刚实例化、未采样完成时,得到的 CPU 占用率可能有误。以下同。
        }
        property AverageCPUUsage: Integer read GetAverageCPUUsage;
        {* 获得平均 CPU 占用率,0 到 100}
        property FirstCPUUsage: Integer read GetFirstCPUUsage;
        {* 获得首个 CPU 的占用率,0 到 100,用于单 CPU 系统}
      end;implementationtype
      _SYSTEM_BASIC_INFORMATION = record
        Unknown: ULONG;
        MaximumIncrement: ULONG;
        PhysicalPageSize: ULONG;
        NumberOfPhysicalPages: ULONG;
        LowestPhysicalPage: ULONG;
        HighestPhysicalPage: ULONG;
        AllocationGranularity: ULONG;
        LowestUserAddress: ULONG;
        HighestUserAddress: ULONG;
        ActiveProcessors: ULONG;
        NumberProcessors: UCHAR;
      end;
      SYSTEM_BASIC_INFORMATION = _SYSTEM_BASIC_INFORMATION;
      PSYSTEM_BASIC_INFORMATION = ^SYSTEM_BASIC_INFORMATION;
      TSystemBasicInformation = SYSTEM_BASIC_INFORMATION;
      PSystemBasicInformation = ^TSystemBasicInformation;  SYSTEM_PROCESSOR_TIMES = packed record
        IdleTime: LARGE_INTEGER;
        KernelTime: LARGE_INTEGER;
        UserTime: LARGE_INTEGER;
        DpcTime: LARGE_INTEGER;
        InterruptTime: LARGE_INTEGER;
        InterruptCount: ULONG;
      end;
      TSystemProcessorTimes = SYSTEM_PROCESSOR_TIMES;
      PSystemProcessorTimes = ^TSystemProcessorTimes;
      
      SYSTEM_INFORMATION_CLASS = (
              SystemBasicInformation,
              SystemProcessorInformation,
              SystemPerformanceInformation,
              SystemTimeOfDayInformation,
              SystemNotImplemented1,
              SystemProcessesAndThreadsInformation,
              SystemCallCounts,
              SystemConfigurationInformation,
              SystemProcessorTimes,
              SystemGlobalFlag,
              SystemNotImplemented2,
              SystemModuleInformation,
              SystemLockInformation,
              SystemNotImplemented3,
              SystemNotImplemented4,
              SystemNotImplemented5,
              SystemHandleInformation,
              SystemObjectInformation,
              SystemPagefileInformation,
              SystemInstructionEmulationCounts,
              SystemInvalidInfoClass1,
              SystemCacheInformation,
              SystemPoolTagInformation,
              SystemProcessorStatistics,
              SystemDpcInformation,
              SystemNotImplemented6,
              SystemLoadImage,
              SystemUnloadImage,
              SystemTimeAdjustment,
              SystemNotImplemented7,
              SystemNotImplemented8,
              SystemNotImplemented9,
              SystemCrashDumpInformation,
              SystemExceptionInformation,
              SystemCrashDumpStateInformation,
              SystemKernelDebuggerInformation,
              SystemContextSwitchInformation,
              SystemRegistryQuotaInformation,
              SystemLoadAndCallImage,
              SystemPrioritySeparation,
              SystemNotImplemented10,
              SystemNotImplemented11,
              SystemInvalidInfoClass2,
              SystemInvalidInfoClass3,
              SystemTimeZoneInformation,
              SystemLookasideInformation,
              SystemSetTimeSlipEvent,
              SystemCreateSession,
              SystemDeleteSession,
              SystemInvalidInfoClass4,
              SystemRangeStartInformation,
              SystemVerifierInformation,
              SystemAddVerifier,
              SystemSessionProcessesInformation);
      TSystemInformationClass = SYSTEM_INFORMATION_CLASS;
      
      TNativeQuerySystemInformation = function(SystemInformationClass:
        TSystemInformationClass; SystemInformation: Pointer; SystemInformationLength:
        Cardinal; ReturnLength: PDWORD): Cardinal; stdcall;
      

  5.   


    const
      STATUS_SUCCESS = $00000000;var
      NtDllHandle: THandle = 0;  NtQuerySystemInformation: TNativeQuerySystemInformation = nil;function GetNtNativeAPIs: Boolean;
    begin
      if Win32Platform = VER_PLATFORM_WIN32_NT then
      begin
        NtDllHandle := GetModuleHandle('NTDLL.DLL');
        if NtDllHandle = 0 then
          NtDllHandle:=LoadLibrary('NTDLL.DLL');    if NtDllHandle <> 0 then
        begin
    //      @NtQueryInformationToken:=GetProcAddress(NtDllHandle,'NtQueryInformationToken');
    //      @NtOpenProcessToken := GetProcAddress(NtDllHandle,'NtOpenProcessToken');
    //      @NtOpenSection := GetProcAddress(NtDllHandle,'NtOpenSection');
    //      @NtClose := GetProcAddress(NtDllHandle,'NtClose');
    //      @NtOpenProcess := GetProcAddress(NtDllHandle,'NtOpenProcess');
          @NtQuerySystemInformation := GetProcAddress(NtDllHandle,'NtQuerySystemInformation');
    //      @NtCreateSection := GetProcAddress(NtDllHandle,'NtCreateSection');
    //      @NtCreateToken := GetProcAddress(NtDllHandle,'NtCreateToken');
    //      @NtMapViewOfSection := GetProcAddress(NtDllHandle,'NtMapViewOfSection');
    //      @NtUnmapViewOfSection := GetProcAddress(NtDllHandle,'NtUnmapViewOfSection');
    //      @NtOpenFile := GetProcAddress(NtDllHandle,'NtOpenFile');
    //      @NtCreateFile := GetProcAddress(NtDllHandle,'NtCreateFile');
    //      @NtQueryObject := GetProcAddress(NtDllHandle,'NtQueryObject');
    //      @NtQueryInformationProcess := GetProcAddress(NtDllHandle,'NtQueryInformationProcess');
    //      @NtQueryInformationThread := GetProcAddress(NtDllHandle,'NtQueryInformationThread');
    //      @NtQueryInformationFile := GetProcAddress(NtDllHandle,'NtQueryInformationFile');
    //      @NtDuplicateObject := GetProcAddress(NtDllHandle,'NtDuplicateObject');
    //      @NtDeviceIoControlFile := GetProcAddress(NtDllHandle,'NtDeviceIoControlFile');
        end;
      end;
      Result := NtDllHandle <> 0;
    end;procedure FreeNtNativeAPIs;
    begin
      if NtDllHandle <> 0 then
      begin
        FreeLibrary(NtDllHandle);
        NtDllHandle := 0;
      end;
    end;constructor TCnCpuId.Create;
    begin
      FCPUIds := TStringList.Create;
      FCPUIdFormat := ifContinuous;
      ReadCPUId;  FTimer := TTimer.Create(nil);
      FTimer.Interval := 1000;
      FTimer.OnTimer := CpuUsageTimer;
      FTimer.Enabled := True;
      RefreshCPUUsages;  if Win32Platform = VER_PLATFORM_WIN32_NT then // NT 下需要采样判断
        FCPUUsageRead := False;
    end;destructor TCnCpuId.Destroy;
    begin
      FTimer.Free;
      FCPUIds.Free;
    end;// 获取所有 CPU 的序列号
    procedure TCnCpuId.ReadCPUId;
    var
      I: Integer;
      Mask: Integer;
      CurrProc: THandle;
      SysInfo: TSystemInfo;
      ProcessAffinityOld: Cardinal;
      ProcessAffinity: Cardinal;
      SystemAffinity: Cardinal;  // 获取 CPU 序列号
      function GetCnCPUID: string;
      const
        cnIFContinuous = '%.8x%.8x%.8x%.8x';
        cnIFDashed = '%.8x-%.8x-%.8x-%.8x';
      var
        iEax,iEbx,iEcx,iEdx: Integer;
      begin
        asm
          push ebx
          push ecx
          push edx
          mov  eax, $1
          dw $A20F      //CPUID
          mov iEax, eax
          mov iEbx, ebx
          mov iEcx, ecx
          mov iEdx, edx
          pop edx
          pop ecx
          pop ebx
        end;
        if FCPUIdFormat=ifContinuous then
          Result := Format(cnIFContinuous, [iEax, iEbx, iEcx, iEdx])
        else
          Result := Format(cnIFDashed, [iEax, iEbx, iEcx, iEdx])
      end;
    begin
      FCPUCount := 0;
      FCPUIds.Clear;
      
      // 获取 CPU 个数
      GetSystemInfo(SysInfo);
      FCPUCount := SysInfo.dwNumberOfProcessors;  // 获取所有 CPU 的序列号
      Mask := $1;
      CurrProc := GetCurrentProcess;
      if not GetProcessAffinityMask(CurrProc, ProcessAffinityOld, SystemAffinity) then
        Exit;
        
      try
        for I:=0 to FCpuCount-1 do
        begin
          ProcessAffinity := Mask shl I;
          if not SetProcessAffinityMask(CurrProc, ProcessAffinity) then
            Break;      FCPUIds.Add(GetCnCPUID);
        end;
      finally
        //恢复默认
        SetProcessAffinityMask(CurrProc, ProcessAffinityOld);
      end;
    end;procedure TCnCpuId.SetCPUIdFormat(ACPUIdFormat: TCnCPUIdFormat);
    begin
      if FCPUIdFormat <> ACPUIdFormat then
      begin
        FCPUIdFormat := ACPUIdFormat;
        ReadCPUId;
      end;
    end;// 获得单 CPU 系统 ID
    function TCnCpuId.GetFirstCPUId: string;
    begin
      if FCPUIds.Count > 0 then
        Result := FCPUIds.Strings[0];
    end;// 得到第几个 CPU 的序列号
    function TCnCpuId.GetCPUId(Index: Integer): string;
    begin
      Result := '';
      // 保证 FCPUIds 索引的合法性
      if (Index < 0) or (Index > FCPUIds.Count - 1) then
        Exit;  Result := FCPUIds.Strings[Index];
    end;function TCnCpuId.GetAverageCPUUsage: Integer;
    begin
      if not FCPUUsageRead then
        Result := -1
      else
        Result := FAverageCPUUsage;
    end;
      

  6.   


    function TCnCpuId.GetCPUUsage(Index: Integer): Integer;
    begin
      if not FCPUUsageRead or (Index > FCPUCount - 1) then
        Result := -1
      else
        Result := FCPUUsage[Index];
    end;function TCnCpuId.GetFirstCPUUsage: Integer;
    begin
      if FCPUUsageRead and (FCPUCount > 0) then
        Result := FCPUUsage[0]
      else
        Result := -1;
    end;function TCnCpuId.RefreshCPUUsages: Cardinal;
    var
      CpuCnt: Cardinal;
      I: integer;
      Spt: Pointer;
      Sbi: TSystemBasicInformation;  dwType, cbData: Cardinal;
      hOpen: HKEY;
      Buffer: Cardinal;
    begin
      if Win32Platform = VER_PLATFORM_WIN32_NT then
      begin
        for I := 0 to FCPUCount - 1 do // 保存旧值
          FLastCnt[I] := FCurCnt[I];    if NtQuerySystemInformation(SystemBasicInformation, @Sbi, SizeOf(Sbi), nil)
          <> STATUS_SUCCESS then
          CpuCnt := 1
        else
          CpuCnt := Sbi.NumberProcessors;    Spt := AllocMem(CpuCnt * (SizeOf(TSystemProcessorTimes) + 4));
        NtQuerySystemInformation(SystemProcessorTimes, Spt, CpuCnt * (SizeOf(TSystemProcessorTimes) + 4), @Result);    for I := 0 to CpuCnt - 1  do
        begin
          with PSystemProcessorTimes(PChar(Spt) + I * (sizeof(TSystemProcessorTimes) + 4))^ do
            FCurCnt[I] := IdleTime.QuadPart;
            
          // 采样后计算
          try
            FCPUUsage[I] := Round((10000000 - (FCurCnt[I] - FLastCnt[I]) / (FTimer.Interval / 1000)) / 10000000 * 100);
          except
            FCPUUsage[I] := 0;
          end;
        end;
        FreeMem(spt);
      end
      else
      begin
        if RegOpenKeyEx(HKEY_DYN_DATA,'PerfStats\StatData', 0, KEY_READ, hOpen) = ERROR_SUCCESS then
        begin
          cbData:=sizeof(Cardinal);
          if RegQueryValueEx(hOpen, 'KERNEL\CPUUsage', nil, @dwType, PBYTE(@Buffer),
            @cbData) = ERROR_SUCCESS then
            FCPUUsage[0] := Buffer;
          RegCloseKey(hOpen);
        end
        else
          FCPUUsage[0] := -1;
      end;  FCPUUsageRead := True;
    end;procedure TCnCpuId.CpuUsageTimer(Sender: TObject);
    var
      I: Integer;
    begin
      RefreshCPUUsages;
      
      FAverageCPUUsage := 0;
      for I := 0 to FCPUCount - 1 do
      begin
        if FCPUUsage[I] <> -1 then
          FAverageCPUUsage := FAverageCPUUsage + FCPUUsage[I];
      end;  if FCPUCount > 0 then
        FAverageCPUUsage := Round(FAverageCPUUsage / FCPUCount)
      else
        FAverageCPUUsage := -1;
    end;initialization
      GetNtNativeAPIs;finalization
      FreeNtNativeAPIs;end.
      

  7.   

    恩 已经知道了GetProcessAffinityMask(CurrProc, ProcessAffinityOld, SystemAffinity)
    这个是关键