function GetHDSerialNumber: LongInt;
{$IFDEF WIN32}
var
  pdw : pDWord;
  mc, fl : dword;
{$ENDIF}
begin
  {$IfDef WIN32}
  New(pdw);
  GetVolumeInformation(nil,nil,0,pdw,mc,fl,nil,0);
  Result := pdw^;
  dispose(pdw);
  {$ELSE}
  Result := GetWinFlags;
  {$ENDIF}
end;

解决方案 »

  1.   

    如何获取硬盘的ID function GetHDSerialNumber(Drv : String): String; 
    var 
    VolumeSerialNumber : DWORD; 
    MaximumComponentLength : DWORD; 
    FileSystemFlags : DWORD; 
    begin 
    if Drv[Length(Drv)] =':' then Drv := Drv + '\'; 
    GetVolumeInformation(pChar(Drv), 
    nil, 
    0, 
    @VolumeSerialNumber, 
    MaximumComponentLength, 
    FileSystemFlags, 
    MaximumComponentLength : DWORD; 
    FileSystemFlags : DWORD; 
    begin 
    if Drv[Length(Drv)] =':' then Drv := Drv + '\'; 
    GetVolumeInformation(pChar(Drv), 
    nil, 
    0, 
    @VolumeSerialNumber, 
    MaximumComponentLength, 
    nil,SystemFlags, 
    0); 
    Result := IntToHex(HiWord(VolumeSerialNumber), 4) + 
    '-' + 
    IntToHex(LoWord(VolumeSerialNumber), 4); 
    end; 
      

  2.   

    如何获取硬盘的ID function GetHDSerialNumber(Drv : String): String; 
    var 
    VolumeSerialNumber : DWORD; 
    MaximumComponentLength : DWORD; 
    FileSystemFlags : DWORD; 
    begin 
    if Drv[Length(Drv)] =':' then Drv := Drv + '\'; 
    GetVolumeInformation(pChar(Drv), 
    nil, 
    0, 
    @VolumeSerialNumber, 
    MaximumComponentLength, 
    FileSystemFlags, 
    MaximumComponentLength : DWORD; 
    FileSystemFlags : DWORD; 
    begin 
    if Drv[Length(Drv)] =':' then Drv := Drv + '\'; 
    GetVolumeInformation(pChar(Drv), 
    nil, 
    0, 
    @VolumeSerialNumber, 
    MaximumComponentLength, 
    nil,SystemFlags, 
    0); 
    Result := IntToHex(HiWord(VolumeSerialNumber), 4) + 
    '-' + 
    IntToHex(LoWord(VolumeSerialNumber), 4); 
    end; 
      

  3.   

    谢谢两位,
    GetVolumeInformation取得的好象是硬盘卷的序列号,
    我想要的是硬盘出厂的序列号,它应该是唯一的,不可变。
      

  4.   

    这位兄台,这个问题你发布了好几次啦,下面的代码你看看对你有没有用,如果有用的话别忘啦加分哟。
    type
      MIDPtr = ^MIDRec;
      MIDRec = Record
        InfoLevel: word;
        SerialNum: LongInt;
        VolLabel: Packed Array [0..10] of Char;
        FileSysType: Packed Array [0..7] of Char;
      end;function GetDriveSerialNum(MID: MIDPtr; drive: Word): Boolean; assembler;
    asm
      push  DS    { Just for safety, I dont think its really needed }
      mov   ax,440Dh { Function Get Media ID }
      mov   bx,drive    { drive no (0-Default, 1-A ...) }
      mov   cx,0866h  { category and minor code }
      lds   dx,MID      { Load pointeraddr. }
      call  DOS3Call   { Supposed to be faster than INT 21H }
      jc    @@err
      mov   al,1           { No carry so return TRUE }
      jmp   @@ok
     @@err:
      mov   al,0           { Carry set so return FALSE }
     @@ok:
      pop   DS            { Restore DS, were not supposed to change it }
    end;procedure TForm1.NrBtnClick(Sender: TObject);
    var
      Info: MIDRec;
    begin
      Info.InfoLevel:=0; { Information Level }
      If GetDriveSerialNum(@Info,0) then  { Do something with it... }
        ListBox.Items.Add(IntToStr(Info.SerialNum)+' '+Info.VolLabel);
    end;--------------------------------------------------------------------------------
    BOOL GetVolumeInformation(    LPCTSTR lpRootPathName, // address of root directory of the file system
        LPTSTR lpVolumeNameBuffer, // address of name of the volume
        DWORD nVolumeNameSize, // length of lpVolumeNameBuffer
        LPDWORD lpVolumeSerialNumber, // address of volume serial number
        LPDWORD lpMaximumComponentLength, // address of system's maximum filename length
        LPDWORD lpFileSystemFlags, // address of file system flags
        LPTSTR lpFileSystemNameBuffer, // address of name of file system
        DWORD nFileSystemNameSize  // length of lpFileSystemNameBuffer
       );--------------------------------------------------------------------------------
    获取SCSI硬盘序列号问题提出/摘要:对于IDE硬盘,你可以使用S.M.A.R.T. API的函数来获取序列号。但对SCSI硬盘,它无法工作。但我们可以使用DeviceIoControl来获取DeviceIoControl设备序列号.  回答:  下面是代码:  program ScsiSN;   // 目的:简单的控制台程序来显示SCSI硬盘的序列号   {$APPTYPE CONSOLE}   uses  Windows, SysUtils;   //-------------------------------------------------------------  function GetDeviceHandle( sDeviceName : String ) : THandle;  begin  Result := CreateFile( PChar('\\.\'+sDeviceName),  GENERIC_READ or GENERIC_WRITE,  FILE_SHARE_READ or FILE_SHARE_WRITE,  nil, OPEN_EXISTING, 0, 0 )  end;   //-------------------------------------------------------------  function ScsiHddSerialNumber( DeviceHandle : THandle ) : String;  {$ALIGN ON}  type  TScsiPassThrough = record  Length : Word;  ScsiStatus : Byte;  PathId : Byte;  TargetId : Byte;  Lun : Byte;  CdbLength : Byte;  SenseInfoLength : Byte;  DataIn : Byte;  DataTransferLength : ULONG;  TimeOutValue : ULONG;  DataBufferOffset : DWORD;  SenseInfoOffset : ULONG;  Cdb : Array[0..15] of Byte;  end;  TScsiPassThroughWithBuffers = record  spt : TScsiPassThrough;  bSenseBuf : Array[0..31] of Byte;  bDataBuf : Array[0..191] of Byte;  end;  {ALIGN OFF}  var dwReturned : DWORD;  len : DWORD;  Buffer : Array[0..255] of Byte;  sptwb : TScsiPassThroughWithBuffers absolute Buffer;  begin  Result := '';  FillChar(Buffer,SizeOf(Buffer),#0);  with sptwb.spt do  begin  Length := SizeOf(TScsiPassThrough);  CdbLength := 6; // CDB6GENERIC_LENGTH  SenseInfoLength := 24;  DataIn := 1; // SCSI_IOCTL_DATA_IN  DataTransferLength := 192;  TimeOutValue := 2;  DataBufferOffset := PChar(@sptwb.bDataBuf)-PChar(@sptwb);  SenseInfoOffset := PChar(@sptwb.bSenseBuf)-PChar(@sptwb);  Cdb[0] := $12; // OperationCode := SCSIOP_INQUIRY;  Cdb[1] := $01; // Flags := CDB_INQUIRY_EVPD; Vital product data  Cdb[2] := $80; // PageCode Unit serial number  Cdb[4] := 192; // AllocationLength  end;  len := sptwb.spt.DataBufferOffset+sptwb.spt.DataTransferLength;  if DeviceIoControl( DeviceHandle, $0004d004, @sptwb, SizeOf(TScsiPassThrough), @sptwb, len, dwReturned, nil )  and ((PChar(@sptwb.bDataBuf)+1)^=#$80)  then  SetString( Result, PChar(@sptwb.bDataBuf)+4,  Ord((PChar(@sptwb.bDataBuf)+3)^) );  end;    //=============================================================  var  hDevice : THandle = 0;  sSerNum, sDeviceName : String;   begin  sDeviceName := ParamStr(1);  if sDeviceName='' then  begin  WriteLn;  WriteLn('Display SCSI-2 device serial number.');  WriteLn;  WriteLn('Using:');  WriteLn;  if Win32Platform=VER_PLATFORM_WIN32_NT then // Windows NT/2000  WriteLn(' ScsiSN PhysicalDrive0')  else  WriteLn(' ScsiSN C:');  WriteLn(' ScsiSN Cdrom0');  WriteLn(' ScsiSN Tape0');  WriteLn;  Exit;  end;  hDevice := GetDeviceHandle(sDeviceName);  if hDevice=INVALID_HANDLE_VALUE then  WriteLn('Error on GetDeviceHandle: ',SysErrorMessage(GetLastError))  else  try  sSerNum := ScsiHddSerialNumber(hDevice);  if sSerNum='' then  WriteLn('Error on DeviceIoControl: ',  SysErrorMessageGetLastError))  else  WriteLn('Device '+sDeviceName  +' serial number = "',sSerNum,'"');  finally  CloseHandle(hDevice);  end;  end.   // 以下站点可获取更多关于SCSI命令的信息:  // ftp://ftp.t10.org/t10/drafts/scsi-1/   // ftp://ftp.t10.org/t10/drafts/spc/   // ftp://ftp.t10.org/t10/drafts/spc2/ --------------------------------------------------------------------------------
    获取光盘序列号uses MMSystem, MPlayer;procedure TForm1.Button1Click(Sender: TObject);
    var
      mp : TMediaPlayer;
      msp : TMCI_INFO_PARMS;
      MediaString : array[0..255] of char;
      ret : longint;
    begin
      mp := TMediaPlayer.Create(nil);
      mp.Visible := false;
      mp.Parent := Application.MainForm;
      mp.Shareable := true;
      mp.DeviceType := dtCDAudio;
      mp.FileName := 'D:';
      mp.Open;
      Application.ProcessMessages;
      FillChar(MediaString, sizeof(MediaString), #0);
      FillChar(msp, sizeof(msp), #0);
      msp.lpstrReturn := @MediaString;
      msp.dwRetSize := 255;
      ret := mciSendCommand(Mp.DeviceId,
                            MCI_INFO,
                            MCI_INFO_MEDIA_IDENTITY,
                            longint(@msp));
      if Ret <> 0 then begin
       MciGetErrorString(ret, @MediaString, sizeof(MediaString));
       Memo1.Lines.Add(StrPas(MediaString));
      end else
        Memo1.Lines.Add(StrPas(MediaString));
      mp.Close;
      Application.ProcessMessages;
      mp.free;
    end;end.
    --------------------------------------------------------------------------------
      

  5.   

    通过它你可以获取型号名称, firmware revision,序列号以及其它有关IDE硬盘的信息.   回答:  相关构件:  IdeInfo.zip  许多FAQ中推荐使用GetVolumeInformation来获取硬盘序列号。但是那获取的是卷的序列号,而不是硬盘的序列号。卷的序列号是在分区格式化时生成或修改。一些公司使用复制工具来为全部新计算机安装软件----通过将一个硬盘复制到其它硬盘,当然,所有这些计算机上卷的信息(包括序列号)都是相同的。    我建议另外的一个方法:获取真正硬盘的序列号。  不幸的是,下列代码只能工作在IDE硬盘上。      //获取第一个IDE硬盘的序列号   function GetIdeSerialNumber : SerialNumber;   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 // Windows NT, Windows 2000   begin   // 提示! 改变名称可适用于其它驱动器,如第二个驱动器: '\\.\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;     // 更多关于 S.M.A.R.T. ioctl 的信息可查看:  // http://www.microsoft.com/hwdev/download/respec/iocltapi.rtf     // MSDN库中也有一些简单的例子  // Windows Development -> Win32 Device Driver Kit ->   // SAMPLE: SmartApp.exe Accesses SMART stats in IDE drives     // 还可以查看 http://www.mtgroup.ru/~alexk   // IdeInfo.zip - 一个简单的使用了S.M.A.R.T. Ioctl API的Delphi应用程序    // 注意:     // WinNT/Win2000 - 你必须拥有对硬盘的读/写访问权限    // Win98   // SMARTVSD.VXD 必须安装到 \windows\system\iosubsys   // (不要忘记在复制后重新启动系统)