为什么那个常见的读硬盘序列号的程序在有的硬盘上能读出来在有的电脑上面却读不出来?在有的电脑上面刚装好XP时可以读出,XP激活后就读不出了,这是怎么回事啊。大部分的都可以读出。部分代码:
if Win32Platform=VER_PLATFORM_WIN32_NT then
  begin   // Windows NT, Windows 2000
                   // Get SCSI port handle
    hDevice := CreateFile( '\\.\Scsi0:',
         GENERIC_READ or GENERIC_WRITE,
         FILE_SHARE_READ or FILE_SHARE_WRITE,
         nil, OPEN_EXISTING, 0, 0 );
    if hDevice=INVALID_HANDLE_VALUE then Exit;
  end………………else
  begin // Windows 95 OSR2, Windows 98
    hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil,
          CREATE_NEW, 0, 0 );
    if hDevice=INVALID_HANDLE_VALUE then Exit;
 end;

解决方案 »

  1.   

    function GetIdeDiskSerialNumber(var SerialNumber: string; var ModelNumber: string;
     var FirmwareRev: string; var TotalAddressableSectors: ULong;
     var SectorCapacity: ULong; var SectorsPerTrack: Word): Boolean; //得到硬盘物理号
    type
     TSrbIoControl = packed record
       HeaderLength: ULong;
       Signature: array[0..7] of Char;
       Timeout: ULong;
       ControlCode: ULong;
       ReturnCode: ULong;
       Length: ULong;
     end;
     SRB_IO_CONTROL = TSrbIoControl;
     PSrbIoControl = ^TSrbIoControl; TIDERegs = packed record
       bFeaturesReg: Byte; // Used for specifying SMART "commands".
       bSectorCountReg: Byte; // IDE sector count register
       bSectorNumberReg: Byte; // IDE sector number register
       bCylLowReg: Byte; // IDE low order cylinder value
       bCylHighReg: Byte; // IDE high order cylinder value
       bDriveHeadReg: Byte; // IDE drive/head register
       bCommandReg: Byte; // Actual IDE command.
       bReserved: Byte; // reserved. Must be zero.
     end;
     IDEREGS = TIDERegs;
     PIDERegs = ^TIDERegs; TSendCmdInParams = packed record
       cBufferSize: DWORD;
       irDriveRegs: TIDERegs;
       bDriveNumber: Byte;
       bReserved: array[0..2] of Byte;
       dwReserved: array[0..3] of DWORD;
       bBuffer: array[0..0] of Byte;
     end;
     SENDCMDINPARAMS = TSendCmdInParams;
     PSendCmdInParams = ^TSendCmdInParams; TIdSector = packed record
       wGenConfig: Word;
       wNumCyls: Word;
       wReserved: Word;
       wNumHeads: Word;
       wBytesPerTrack: Word;
       wBytesPerSector: Word;
       wSectorsPerTrack: Word;
       wVendorUnique: array[0..2] of Word;
       sSerialNumber: array[0..19] of Char;
       wBufferType: Word;
       wBufferSize: Word;
       wECCSize: Word;
       sFirmwareRev: array[0..7] of Char;
       sModelNumber: array[0..39] of Char;
       wMoreVendorUnique: Word;
       wDoubleWordIO: Word;
       wCapabilities: Word;
       wReserved1: Word;
       wPIOTiming: Word;
       wDMATiming: Word;
       wBS: Word;
       wNumCurrentCyls: Word;
       wNumCurrentHeads: Word;
       wNumCurrentSectorsPerTrack: Word;
       ulCurrentSectorCapacity: ULong;
       wMultSectorStuff: Word;
       ulTotalAddressableSectors: ULong;
       wSingleWordDMA: Word;
       wMultiWordDMA: Word;
       bReserved: array[0..127] of Byte;
     end;
     PIdSector = ^TIdSector;const
     IDE_ID_FUNCTION = $EC;
     IDENTIFY_BUFFER_SIZE = 512;
     DFP_RECEIVE_DRIVE_DATA = $0007C088;
     IOCTL_SCSI_MINIPORT = $0004D008;
     IOCTL_SCSI_MINIPORT_IDENTIFY = $001B0501;
     DataSize = sizeof(TSendCmdInParams) - 1 + IDENTIFY_BUFFER_SIZE;
     BufferSize = sizeof(SRB_IO_CONTROL) + DataSize;
     W9xBufferSize = IDENTIFY_BUFFER_SIZE + 16;
    var
     hDevice: THandle;
     cbBytesReturned: DWORD;
     pInData: PSendCmdInParams;
     pOutData: Pointer; // PSendCmdOutParams
     Buffer: array[0..BufferSize - 1] of Byte;
     srbControl: TSrbIoControl absolute Buffer; procedure ChangeByteOrder(var Data; Size: Integer);
     var ptr: PChar;
       i: Integer;
       c: Char;
     begin
       ptr := @Data;
       for i := 0 to (Size shr 1) - 1 do
       begin
         c := ptr^;
         ptr^ := (ptr + 1)^;
         (ptr + 1)^ := c;
         Inc(ptr, 2);
       end;
     end;begin
     Result := False;
     FillChar(Buffer, BufferSize, #0);
     if Win32Platform = VER_PLATFORM_WIN32_NT then
     begin // Windows NT, Windows 2000
    // Get SCSI port handle
       hDevice := CreateFile('\\.\Scsi0:',
         GENERIC_READ or GENERIC_WRITE,
         FILE_SHARE_READ or FILE_SHARE_WRITE,
         nil, OPEN_EXISTING, 0, 0);
       if hDevice = INVALID_HANDLE_VALUE then Exit;
       try
         srbControl.HeaderLength := sizeof(SRB_IO_CONTROL);
         System.Move('SCSIDISK', srbControl.Signature, 8);
         srbControl.Timeout := 2;
         srbControl.Length := DataSize;
         srbControl.ControlCode := IOCTL_SCSI_MINIPORT_IDENTIFY;
         pInData := PSendCmdInParams(PChar(@Buffer)
           + sizeof(SRB_IO_CONTROL));
         pOutData := pInData;
         with pInData^ do
         begin
           cBufferSize := IDENTIFY_BUFFER_SIZE;
           bDriveNumber := 0;
           with irDriveRegs do
           begin
             bFeaturesReg := 0;
             bSectorCountReg := 1;
             bSectorNumberReg := 1;
             bCylLowReg := 0;
             bCylHighReg := 0;
             bDriveHeadReg := $A0;
             bCommandReg := IDE_ID_FUNCTION;
           end;
         end;
         if not DeviceIoControl(hDevice, IOCTL_SCSI_MINIPORT,
           @Buffer, BufferSize, @Buffer, BufferSize,
           cbBytesReturned, nil) then Exit;
       finally
         CloseHandle(hDevice);
       end;
     end
     else
     begin // Windows 95 OSR2, Windows 98
       hDevice := CreateFile('\\.\SMARTVSD', 0, 0, nil,
         CREATE_NEW, 0, 0);
       if hDevice = INVALID_HANDLE_VALUE then Exit;
       try
         pInData := PSendCmdInParams(@Buffer);
         pOutData := @pInData^.bBuffer;
         with pInData^ do
         begin
           cBufferSize := IDENTIFY_BUFFER_SIZE;
           bDriveNumber := 0;
           with irDriveRegs do
           begin
             bFeaturesReg := 0;
             bSectorCountReg := 1;
             bSectorNumberReg := 1;
             bCylLowReg := 0;
             bCylHighReg := 0;
             bDriveHeadReg := $A0;
             bCommandReg := IDE_ID_FUNCTION;
           end;
         end;
         if not DeviceIoControl(hDevice, DFP_RECEIVE_DRIVE_DATA,
           pInData, sizeof(TSendCmdInParams) - 1, pOutData,
           W9xBufferSize, cbBytesReturned, nil) then Exit;
       finally
         CloseHandle(hDevice);
       end;
     end;
     with PIdSector(PChar(pOutData) + 16)^ do
     begin
       ChangeByteOrder(sSerialNumber, sizeof(sSerialNumber));
       SetString(SerialNumber, sSerialNumber, sizeof(sSerialNumber)); //硬盘生产序号   ChangeByteOrder(sModelNumber, sizeof(sModelNumber));
       SetString(ModelNumber, sModelNumber, sizeof(sModelNumber)); //硬盘型号   ChangeByteOrder(sFirmwareRev, sizeof(sFirmwareRev));
       SetString(FirmwareRev, sFirmwareRev, sizeof(sFirmwareRev)); //硬盘硬件版本
       Result := True;
       ChangeByteOrder(ulTotalAddressableSectors, sizeof(ulTotalAddressableSectors));
       TotalAddressableSectors := ulTotalAddressableSectors; //硬盘ulTotalAddressableSectors参数   ChangeByteOrder(ulCurrentSectorCapacity, sizeof(ulCurrentSectorCapacity));
       SectorCapacity := ulCurrentSectorCapacity; //硬盘wBytesPerSector参数   ChangeByteOrder(wNumCurrentSectorsPerTrack, sizeof(wNumCurrentSectorsPerTrack));
       SectorsPerTrack := wNumCurrentSectorsPerTrack; //硬盘wSectorsPerTrack参数
     end;
    end;procedure TFrmMain.FormCreate(Sender: TObject);
    var
     S1, S2, S3: string;
     W5: Word;
     W4, W3: ULong;
    begin
      GetIdeDiskSerialNumber(S1, S2, S3, W3, W4, W5);
      Showmessage('硬盘序列号'+s1);
    end;试试这个,如果可以的话给我发短消息.
      

  2.   

    //获取硬盘序列号
    //win98要 c:\windows\system\的smartvsd.vxd
    //copy to c:\windows\system\iosubsys
    //reboot your computer and ok
    //2000 and nt do not need
    function GetIdeSerialNumber: String;
    const
      IDENTIFY_BUFFER_SIZE = 512;
    type
       TIDERegs = packed record
        bFeaturesReg     : BYTE; // Used for specifying SMART "commands".
        bSectorCountReg  : BYTE; // IDE sector count register
        bSectorNumberReg : BYTE; // IDE sector number register
        bCylLowReg       : BYTE; // IDE low order cylinder value
        bCylHighReg      : BYTE; // IDE high order cylinder value
        bDriveHeadReg    : BYTE; // IDE drive/head register
        bCommandReg      : BYTE; // Actual IDE command.
        bReserved        : BYTE; // reserved for future use.  Must be zero.
      end;
      TSendCmdInParams = packed record
        // Buffer size in bytes
        cBufferSize  : DWORD;
        // Structure with drive register values.
        irDriveRegs  : TIDERegs;
        // Physical drive number to send command to (0,1,2,3).
        bDriveNumber : BYTE;
        bReserved    : Array[0..2] of Byte;
        dwReserved   : Array[0..3] of DWORD;
        bBuffer      : Array[0..0] of Byte;  // Input buffer.
      end;
      TIdSector = packed record
        wGenConfig                 : Word;
        wNumCyls                   : Word;
        wReserved                  : Word;
        wNumHeads                  : Word;
        wBytesPerTrack             : Word;
        wBytesPerSector            : Word;
        wSectorsPerTrack           : Word;
        wVendorUnique              : Array[0..2] of Word;
        sSerialNumber              : Array[0..19] of CHAR;
        wBufferType                : Word;
        wBufferSize                : Word;
        wECCSize                   : Word;
        sFirmwareRev               : Array[0..7] of Char;
        sModelNumber               : Array[0..39] of Char;
        wMoreVendorUnique          : Word;
        wDoubleWordIO              : Word;
        wCapabilities              : Word;
        wReserved1                 : Word;
        wPIOTiming                 : Word;
        wDMATiming                 : Word;
        wBS                        : Word;
        wNumCurrentCyls            : Word;
        wNumCurrentHeads           : Word;
        wNumCurrentSectorsPerTrack : Word;
        ulCurrentSectorCapacity    : DWORD;
        wMultSectorStuff           : Word;
        ulTotalAddressableSectors  : DWORD;
        wSingleWordDMA             : Word;
        wMultiWordDMA              : Word;
        bReserved                  : Array[0..127] of BYTE;
      end;
      PIdSector = ^TIdSector;
      TDriverStatus = packed record
        // 驱动器返回的错误代码,无错则返回0
        bDriverError : Byte;
        // IDE出错寄存器的内容,只有当bDriverError 为 SMART_IDE_ERROR 时有效
        bIDEStatus   : Byte;
        bReserved    : Array[0..1] of Byte;
        dwReserved   : Array[0..1] of DWORD;
      end;
      TSendCmdOutParams = packed record
        // bBuffer的大小
        cBufferSize  : DWORD;
        // 驱动器状态
        DriverStatus : TDriverStatus;
        // 用于保存从驱动器读出的数据的缓冲区,实际长度由cBufferSize决定
        bBuffer      : Array[0..0] of BYTE;
      end;
    var
      hDevice : THandle;
      cbBytesReturned : DWORD;
      ptr : PChar;
      SCIP : TSendCmdInParams;
      aIdOutCmd : Array [0..(SizeOf(TSendCmdOutParams)+IDENTIFY_BUFFER_SIZE-1)-1] of Byte;
      IdOutCmd  : TSendCmdOutParams absolute aIdOutCmd;  procedure ChangeByteOrder( var Data; Size : Integer );
      var ptr : PChar;
          i : Integer;
          c : Char;
      begin
        ptr := @Data;
        for i := 0 to (Size shr 1)-1 do begin
          c := ptr^;
          ptr^ := (ptr+1)^;
          (ptr+1)^ := c;
          Inc(ptr,2);
        end;
     end;begin
      Result := ''; // 如果出错则返回空串
      if SysUtils.Win32Platform=VER_PLATFORM_WIN32_NT then begin// Windows NT, Windows 2000
          // 提示! 改变名称可适用于其它驱动器,如第二个驱动器: '\\.\PhysicalDrive1\'
          hDevice := CreateFile( '\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,
            FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 );
      end else // Version Windows 95 OSR2, Windows 98
        hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 );
        if hDevice=INVALID_HANDLE_VALUE then Exit;
       try
        FillChar(SCIP,SizeOf(TSendCmdInParams)-1,#0);
        FillChar(aIdOutCmd,SizeOf(aIdOutCmd),#0);
        cbBytesReturned := 0;
        // Set up data structures for IDENTIFY command.
        with SCIP do begin
          cBufferSize  := IDENTIFY_BUFFER_SIZE;
          //bDriveNumber := 0;
          with irDriveRegs do begin
            bSectorCountReg  := 1;
            bSectorNumberReg := 1;
            //if Win32Platform=VER_PLATFORM_WIN32_NT then bDriveHeadReg := $A0
            //else bDriveHeadReg := $A0 or ((bDriveNum and 1) shl 4);
            bDriveHeadReg    := $A0;
            bCommandReg      := $EC;
          end;
        end;
        if not DeviceIoControl( hDevice, $0007c088, @SCIP, SizeOf(TSendCmdInParams)-1,
          @aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil ) then Exit;
      finally
        CloseHandle(hDevice);
      end;
      with PIdSector(@IdOutCmd.bBuffer)^ do begin
        ChangeByteOrder( sSerialNumber, SizeOf(sSerialNumber) );
        (PChar(@sSerialNumber)+SizeOf(sSerialNumber))^ := #0;
        ptr := PChar(@sSerialNumber);
        Result := Trim(ptr);
      end;
    end;
      

  3.   

    上面那个估计对已MiniPort的IDE或SCSI是没用的要用GetScsiInquiryData才OK的都不知道维护FAQ的版筑去那里了,N日都没有审核我的FAQ郁闷看http://community.csdn.net/Expert/topic/3311/3311236.xml?temp=.1030695了提交去FAQ居然2周都没人理:(http://lysoft.7u7.net
      

  4.   

    wintergoes(多来米饭少来稀) 老兄的在有的机子上也不可以。
      

  5.   

    不是IDE,或系统是98 建议你还取CPUID,
      

  6.   

    靠,我们的CPU还是64位的。IDE硬盘SCSI控制器,XP系统。
      

  7.   

    取序列号(CPU,硬盘,网卡)控件下载:
    Http://www.datcn.com/downloads/hardwareinfo.exe
      

  8.   

    第一个接口问题.
    第二可能系列号就为空.比如:
    function GetIdeSerialNumber: pchar;
      const IDENTIFY_BUFFER_SIZE = 512;
    type
       TIDERegs = packed record
         bFeaturesReg: BYTE; // Used for specifying SMART "commands".
         bSectorCountReg: BYTE; // IDE sector count register
         bSectorNumberReg: BYTE; // IDE sector number register
         bCylLowReg: BYTE; // IDE low order cylinder value
         bCylHighReg: BYTE; // IDE high order cylinder value
         bDriveHeadReg: BYTE; // IDE drive/head register
         bCommandReg: BYTE; // Actual IDE command.
         bReserved: BYTE; // reserved for future use. Must be zero.
      end;
      TSendCmdInParams = packed record
        // Buffer size in bytes
        cBufferSize: DWORD;
        // Structure with drive register values.
        irDriveRegs: TIDERegs;
        // Physical drive number to send command to (0,1,2,3).
        bDriveNumber: BYTE;
        bReserved: array[0..2] of Byte;
        dwReserved: array[0..3] of DWORD;
        bBuffer: array[0..0] of Byte; // Input buffer.
      end;
      TIdSector = packed record
        wGenConfig: Word;
        wNumCyls: Word;
        wReserved: Word;
        wNumHeads: Word;
        wBytesPerTrack: Word;
        wBytesPerSector: Word;
        wSectorsPerTrack: Word;
        wVendorUnique: array[0..2] of Word;
        sSerialNumber: array[0..19] of CHAR;
        wBufferType: Word;
        wBufferSize: Word;
        wECCSize: Word;
        sFirmwareRev: array[0..7] of Char;
        sModelNumber: array[0..39] of Char;
        wMoreVendorUnique: Word;
        wDoubleWordIO: Word;
        wCapabilities: Word;
        wReserved1: Word;
        wPIOTiming: Word;
        wDMATiming: Word;
        wBS: Word;
        wNumCurrentCyls: Word;
        wNumCurrentHeads: Word;
        wNumCurrentSectorsPerTrack: Word;
        ulCurrentSectorCapacity: DWORD;
        wMultSectorStuff: Word;
        ulTotalAddressableSectors: DWORD;
        wSingleWordDMA: Word;
        wMultiWordDMA: Word;
        bReserved: array[0..127] of BYTE;
      end;
      PIdSector = ^TIdSector;
      TDriverStatus = packed record
        // 驱动器返回的错误代码,无错则返回0
        bDriverError: Byte;
        // IDE出错寄存器的内容,只有当bDriverError 为 SMART_IDE_ERROR 时有效
        bIDEStatus: Byte;
        bReserved: array[0..1] of Byte;
        dwReserved: array[0..1] of DWORD;
      end;
      TSendCmdOutParams = packed record
        // bBuffer的大小
        cBufferSize: DWORD;
        // 驱动器状态
        DriverStatus: TDriverStatus;
        // 用于保存从驱动器读出的数据的缓冲区,实际长度由cBufferSize决定
        bBuffer: array[0..0] of BYTE;
      end;
    var
      hDevice: Thandle;
      cbBytesReturned: DWORD;
      SCIP: TSendCmdInParams;
      aIdOutCmd: array[0..(SizeOf(TSendCmdOutParams) + IDENTIFY_BUFFER_SIZE-1)-1] of Byte;
      IdOutCmd: TSendCmdOutParams absolute aIdOutCmd;
    procedure ChangeByteOrder(var Data; Size: Integer);
    var
      ptr: Pchar;
      i: Integer;
      c: Char;
    begin
      ptr := @Data;
      for I := 0 to (Size shr 1) - 1 do begin
        c := ptr^;
        ptr^ := (ptr + 1)^;
        (ptr + 1)^ := c;
        Inc(ptr, 2);
      end;
    end;
    begin
    Result := ''; // 如果出错则返回空串
    if SysUtils.Win32Platform = VER_PLATFORM_WIN32_NT then begin // Windows NT, Windows 2000
    // 提示! 改变名称可适用于其它驱动器,如第二个驱动器: '\\.\PhysicalDrive1\'
    hDevice := CreateFile('\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,
    FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
    end else // Version Windows 95 OSR2, Windows 98
    hDevice := CreateFile('\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0);
    if hDevice = INVALID_HANDLE_VALUE then Exit;
    try
    FillChar(SCIP, SizeOf(TSendCmdInParams) - 1, #0);
    FillChar(aIdOutCmd, SizeOf(aIdOutCmd), #0);
    cbBytesReturned := 0;
    // Set up data structures for IDENTIFY command.
    with SCIP do begin
    cBufferSize := IDENTIFY_BUFFER_SIZE;
    // bDriveNumber := 0;
    with irDriveRegs do begin
    bSectorCountReg := 1;
    bSectorNumberReg := 1;
    // if Win32Platform=VER_PLATFORM_WIN32_NT then bDriveHeadReg := $A0
    // else bDriveHeadReg := $A0 or ((bDriveNum and 1) shl 4);
    bDriveHeadReg := $A0;
    bCommandReg := $EC;
    end;
    end;
    if not DeviceIoControl(hDevice, $0007C088, @SCIP, SizeOf(TSendCmdInParams) - 1,
    @aIdOutCmd, SizeOf(aIdOutCmd), cbBytesReturned, nil) then Exit;
    finally
    CloseHandle(hDevice);
    end;
    with PIdSector(@IdOutCmd.bBuffer)^ do begin
    ChangeByteOrder(sSerialNumber, SizeOf(sSerialNumber));
    (Pchar(@sSerialNumber) + SizeOf(sSerialNumber))^:= #0;
    Result := Pchar(@sSerialNumber);
    end;
    end;//调用方法
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Edit1.Text:=strpas(GetIdeSerialNumber);
    end;上面这段代码就读不出DELL的计算机的系列号.
    在使用的使用建议加上CPUID,但是同一型号的硬盘系列号一样.同一型号的CPUID也一样。在使用的时候可以增加一个随机.这个值你可以写到文件或者EXE的间隙里.