不知道行不行,你可以试试看:
Unit HardDisk;
INTERFACE
FUNCTION  GetHardDiskNaam  : STRING;
FUNCTION  GetHardDiskSerieNummer        : STRING;
FUNCTION  GetHardDiskControlleNummer    : STRING;
PROCEDURE GetHardDiskGegevens;
CONST
  CodeerTabel : ARRAY[0..24] OF BYTE =
(3,1,2,1,4,1,3,2,6,4,6,5,1,2,6,4,2,6,3,4,6,2,4,1,2);
TYPE
  CharArray = ARRAY[0..24] OF CHAR;
VAR
  HardDiskGegevens          : ARRAY[1..256] OF INTEGER;
  HardDiskNaam  : CharArray;
  SerieNummer  : CharArray;
  ControlleNummer          : CharArray;
  C_HardDiskNaam: STRING;
  C_HardDiskSerieNummer    : STRING;
  C_HardDiskControlleNummer : STRING;
  C_LicentieNaam: STRING;
IMPLEMENTATION
FUNCTION GetHardDiskNaam : STRING;
VAR
  Teller : INTEGER;
  Lus    : INTEGER;
BEGIN
    GetHardDiskNaam := '';
    Teller := 1;
    FOR Lus := 1 TO 18 DO
    BEGIN
      HardDiskNaam[Teller] := CHR( ( HardDiskGegevens[27+Lus] DIV 256 ));
      Inc(Teller);
      HardDiskNaam[Teller] := CHR( ( HardDiskGegevens[27+Lus] MOD 256 ));
      Inc(Teller);
    END;
    GetHardDiskNaam := HardDiskNaam;
END;
FUNCTION GetHardDiskSerieNummer : STRING;
VAR
  Teller : INTEGER;
  Lus    : INTEGER;
BEGIN
    GetHardDiskSerieNummer := '';
    Teller := 1;
    FOR Lus := 1 TO 8 DO
    BEGIN
      SerieNummer[Teller] := CHR( ( HardDiskGegevens[10+Lus] DIV 256 ));
      Inc(Teller);
      SerieNummer[Teller] := CHR( ( HardDiskGegevens[10+Lus] MOD 256 ));
      Inc(Teller);
    END;
    GetHardDiskSerieNummer := SerieNummer;
END;
FUNCTION GetHardDiskControlleNummer : STRING;
VAR
  Teller : INTEGER;
  Lus    : INTEGER;
BEGIN
    GetHardDiskControlleNummer := '';
    Teller := 1;
    FOR Lus := 1 TO 3 DO
    BEGIN
      ControlleNummer[Teller] := CHR( ( HardDiskGegevens[23+Lus] DIV 256 ));
      Inc(Teller);
      ControlleNummer[Teller] := CHR( ( HardDiskGegevens[23+Lus] MOD 256 ));
      Inc(Teller);
    END;
    GetHardDiskControlleNummer := ControlleNummer;
END;
PROCEDURE GetHardDiskGegevens;
VAR
  Lus    : INTEGER;
BEGIN
  WHILE ( Port[$1f7] <> $50) DO ;
  Port[$1F6] := $A0 ;
  Port[$1F7] := $EC ;
  WHILE ( Port[$1f7] <> $58 ) DO ;
  FOR Lus := 1 TO 256 DO
  BEGIN
    HardDiskGegevens[Lus] := Portw[$1F0] ;
  END;
END;
END.

解决方案 »

  1.   


      一、 用GetDriveType函数获取磁盘信息  
      Lbl_DriveType:Tlabel; 
      DriveType:WORD; //定义驱动器类型变量 
      DriveType:=GetDriveType(RootPathName); //获得RootPathName所对应的磁盘驱动器信息 
      case DriveType of 
      DRIVE_REMOVABLE:Lbl_DriveType.Caption:= '软盘驱动器'; 
      DRIVE_FIXED : Lbl_DriveType.Caption:= '硬盘驱动器'; 
      DRIVE_REMOTE: Lbl_DriveType.Caption:= '网络驱动器'; 
      DRIVE_CDROM: Lbl_DriveType.Caption:= '光盘驱动器'; 
      DRIVE_RAMDISK: Lbl_DriveType.Caption:= '内存虚拟盘'; 
      end; //将该磁盘信息显示在Lbl_DriveType中 作者:kongfang(bnnay)    来源:210.28.70.67
    标题:如何获得硬盘的序列号-程序清单
    声明:不能用于NT
    unit Unit1;
    interface
    uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
    Dialogs,
    StdCtrls;
    type
    TForm1 = class(TForm)
      Button1: TButton;
      Label0: TLabel;
      Label1: TLabel;
      Label2: TLabel;
      Label3: TLabel;
      Label4: TLabel;
      procedure Button1Click(Sender: TObject);
    private
      { Private declarations }
    public
      { Public declarations }
    end;
    const
    hookexceptionno = 5;
    ErrNo : integer =0;
    var
    pw : array [0..255] of WORD;//    pw[256];
    idtr_1 : array [0..5] of byte; //保存中断描述符表寄存器
    oldexceptionhook : dword;      //保存原先的中断入口地址
    IdeBase : word;
    SelectDisk: integer;
    var
    Form1: TForm1;
    implementation
    {$R *.DFM}
    function  inp(rdx:word) : byte;
    asm
      mov dx, rdx
      in al, dx
    end;
    function inpw(rdx: word) : word;
    asm
      mov dx, rdx
      in  ax, dx
    end;
    procedure outp(ral : byte; rdx : word);
    asm
      mov dx, rdx
      mov al, ral
      out dx, al
    end;
    function WaitIde:byte;
    var
    al:byte;
    begin
    repeat
      al:=inp(IdeBase+7);
    until (al<$80) or (al=$a0); //$a0可能就没有硬盘
    WaitIde := al;
    end;
    procedure ReadIDE;
    var
    al : byte;
    i : integer;
    begin
    WaitIde;
    outp(SelectDisk,IdeBase+6);
    al := WaitIde;
    if ((al and $50) <>$50) then
    begin
      ErrNo:=1;
      exit;
    end;
    outp(SelectDisk,IdeBase+6);
    outp($EC,IdeBase+7);
    al := WaitIde;
    if ((al and $58)<>$58) then
    begin
      ErrNo:=2;
      exit;
    end;
    for i:=0 to 255 do
    begin
      pw[i] := inpw(IdeBase);
    end;
    end;
    // 新的中断处理程序
    procedure ReadIt; assembler;
    asm
      push eax
      push ebx
      push ecx
      push edx
      push esi
      push edi
      // 在这里写读程序
      call ReadIDE
      pop edi
      pop esi
      pop edx
      pop ecx
      pop ebx
      pop eax
      iretd
    end;
    procedure GetSerialNo; assembler;
    begin
    asm
      push eax
      // 获取修改的中断的中断描述符(中断门)地址
      sidt idtr_1
      mov eax,dword ptr idtr_1+02h
      add eax,hookexceptionno*08h+04h
      // 保存原先的中断入口地址
      cli
      push ecx
      mov ecx,dword ptr [eax]
      mov cx,word ptr [eax-04h]
      mov dword ptr oldexceptionhook,ecx
      pop ecx
      // 设置修改的中断入口地址为新的中断处理程序入口地址
      push ebx
      lea ebx,ReadIt
      mov word ptr [eax-04h],bx
      shr ebx,10h
      mov word ptr [eax+02h],bx
      pop ebx
      // 执行中断,转到ring 0(与cih 病毒原理相似!)
      push ebx
      int hookexceptionno
      pop ebx
      // 恢复原先的中断入口地址
      push ecx
      mov ecx,dword ptr oldexceptionhook
      mov word ptr [eax-04h],cx
      shr ecx,10h
      mov word ptr [eax+02h],cx
      pop ecx
      // 结束
      sti
      pop eax
      ret
    end;
    end;
    procedure GetPN(DriveNo: integer; var s:string);
    var
    i : integer;
    begin
    //  asm int 3 end;
    ErrNo:=0;
    fillchar(pw,sizeof(pw),0);
    s:='';
    case DriveNo of      //设置基址
      0,1:IdeBase:= $1f0;
      2,3:IdeBase:= $170;
    end;
    case DriveNo of      //指定主从
      0,2:SelectDisk:=$A0;
      1,3:SelectDisk:=$B0;
    end;
    GetSerialNo;
    if ErrNo<>0 then
      exit;      //读错误
    if (pw[0]=0) then
      s := '没有序列号:('
    else
      for i:=10 to 20 do
      begin
        s := s+ char(pw[i] shr 8) + char(pw[i] and $ff);
      end;
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    var
    s:string;
    i:integer;
    begin
    for i:=0 to 3 do
    begin
      GetPN(i, s);
      if (s<>'') then
      case i of
        0:  Label1.Caption := 'IDE1 主盘' +s;
        1:  Label2.Caption := 'IDE1 从盘' +s;
        2:  Label3.Caption := 'IDE2 主盘' +s;
        3:  Label3.Caption := 'IDE2 从盘' +s;
      end;
    end;
    end;
    end.
      

  2.   

    可以获得硬盘的型号、序列号以及计算机 ID,带Delphi的源程序,在Win2K下通过,但是没有在Win9X下试过,感兴趣的朋友可以在Win9X 下试一下,或者编写一个VB的范例。
    函数以及定义:
    function ReadPhysicalDrive(driveID:integer;buffer:Pointer;bufLen:integer):integer; stdcall; external 'DiskID.dll' name 'ReadPhysicalDriveInNT';
    获得WinNT下的硬盘型号以及序列号。参数driveID为硬盘的位置,IDE1上的主盘为0,类推到IDE2上的从盘的driveID为3。
    function ReadPhysicalDrive9X(driveID:integer;buffer:Pointer;bufLen:integer):integer; stdcall; external 'DiskID.dll' name 'ReadDrivePortsInWin9X'; 
    获得Win9X下的硬盘型号以及序列号。参数同上
    function getHardDriveComputerID:int64; stdcall; external 'DiskID.dll' name 'getHardDriveComputerID';
    获得计算机的ID 
    http://www.applevb.com/lib/diskio.rar
      

  3.   

    TechnoFantasy(www.applevb.com):能否告知源码,而不是DLL。另:我需要的是win2000的读硬盘物理ID。
      

  4.   

    如果硬盘本身无出厂序列号, 则以上代码就无用武之地了!就返回相同的值。有没有高手能实现像美萍一样读唯一主板序列号(Win9X/ME/2K/NT/XP操作系统都要相同)....