网上关于此问题的帖子满天飞,可没发现一个能在98下取到硬盘序列号的,请您测试一下再发表言论

解决方案 »

  1.   

    Unit HardDisk;INTERFACEFUNCTION GetHardDiskNaam : STRING;FUNCTION GetHardDiskSerieNummer : STRING;FUNCTION GetHardDiskControlleNummer : STRING;PROCEDURE GetHardDiskGegevens;CONSTCodeerTabel : 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);TYPECharArray = ARRAY[0..24] OF CHAR;VARHardDiskGegevens : ARRAY[1..256] OF INTEGER;HardDiskNaam : CharArray;SerieNummer : CharArray;ControlleNummer : CharArray;C_HardDiskNaam: STRING;C_HardDiskSerieNummer : STRING;C_HardDiskControlleNummer : STRING;C_LicentieNaam: STRING;IMPLEMENTATIONFUNCTION GetHardDiskNaam : STRING;VARTeller : INTEGER;Lus : INTEGER;BEGINGetHardDiskNaam := '';Teller := 1;FOR Lus := 1 TO 18 DOBEGINHardDiskNaam[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;VARTeller : INTEGER;Lus : INTEGER;BEGINGetHardDiskSerieNummer := '';Teller := 1;FOR Lus := 1 TO 8 DOBEGINSerieNummer[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;VARTeller : INTEGER;Lus : INTEGER;BEGINGetHardDiskControlleNummer := '';Teller := 1;FOR Lus := 1 TO 3 DOBEGINControlleNummer[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;VARLus : INTEGER;BEGINWHILE ( Port[$1f7] <> $50) DO ;Port[$1F6] := $A0 ;Port[$1F7] := $EC ;WHILE ( Port[$1f7] <> $58 ) DO ;FOR Lus := 1 TO 256 DOBEGINHardDiskGegevens[Lus] := Portw[$1F0] ;END;END;END.
      

  2.   

    读IDE硬盘序列号的DLL原码
    library ReadDiskSrNo;
    uses
    sharemem, //这个必须加上
    dialogs,
    ReadDskSNo in ‘ReadDskSNo.pas‘,
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    StdCtrls;//function GetIdeDiskSerialNumber : String; export;改成
    function GetIdeDiskSerialNumber:pchar; stdcall;
    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 := allocMem(254); 
    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(Result,sSerialNumber,SizeOf(sSerialNumber)); 
    result:=sSerialNumber;
    end; 
    end;exports
    GetIdeDiskSerialNumber index 1;
    begin
    end.
    ————————unit ReadDskSNo;
    interface
    function GetIdeDiskSerialNumber:[gold]pchar[/gold];implementation
    function GetIdeDiskSerialNumber:[red]pchar[/red]; external ‘ReadDiskSrNo‘ index 1;
    end.
      

  3.   

    打开delphi,新建一个工程,在Form上放一个Edit,一个Button,在把下面的代码拷过去就可以了,OK,祝你好运。 unit Unit1;interfaceuses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls;type
    TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    private
    { Private declarations }
    public
    { Public declarations }
    end;{*******Use in Win2k ****************}
    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;{************end Win2k*****************}const
    {********** Use in Win2k **********}
    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;
    {********* End Win2k***************}{********* Use in Win9x ***********}
    hookexceptionno = 5;
    {********* End in Win9x************}var
    Form1: TForm1;{********* Use in Win9x ***********}
    pw : array [0..255] of Word;// pw[256];
    idtr_1 : array [0..5] of Byte; //保存中断描述符表寄存器
    oldexceptionhook : DWord; //保存原先的中断入口地址
    IdeBase : Word;
    SelectDisk: Integer;
    ErrNo : Integer = 0;
    {********* End in Win9x************}implementation{$R *.dfm}{********* Use in Win9x ***********}
    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;
    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;procedure GetIdeDiskSN9X(DriverNo: integer; var s:string);
    var
    i: Integer;
    begin
    {如果有多硬盘一般可能有4个硬盘,也可能多至8个硬盘}
    ErrNo:=0;
    fillchar(pw,sizeof(pw),0);
    s:='';{设置基址,
    4,5:IdeBase := $1e8;
    6,7:IdeBase := $168;}
    case DriverNo of
    0,1: IdeBase := $1f0;
    2,3: IdeBase := $170;
    end;{ 指定主从,Driver No 是奇数为$B0,偶数为$A0}
    case DriverNo 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;
    {********* End in Win9x************}{*******Use in Win2k ****************}
    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;
    { Windows NT, Windows 2000
    通过MS的S.M.A.R.T.接口,直接从RING3调用
    API DeviceIoControl()来获取硬盘信息
    Get SCSI port handle}
    function GetIdeDiskSNNT : String;
    var
    hDevice: THandle;
    cbBytesReturned: DWORD;
    pInData: PSendCmdInParams;
    pOutData: Pointer; // PSendCmdOutParams
    Buffer: Array[0..BufferSize-1] of Byte;
    srbControl: TSrbIoControl absolute Buffer;
    begin
    Result := '';
    FillChar(Buffer,BufferSize,#0);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;with PIdSector(PChar(pOutData)+16)^ do
    begin
    ChangeByteOrder(sSerialNumber,SizeOf(sSerialNumber));
    SetString(Result,sSerialNumber,SizeOf(sSerialNumber));
    end;
    Result := Trim(Result);
    end;
    {********* End in Win2k************}function getIDEHardDiskSN: String;
    begin
    if Win32Platform = VER_PLATFORM_WIN32_NT then
    Result := getIDEDiskSNNT
    else if Win32Platform = VER_PLATFORM_WIN32_WINDOWS then
    getIDEDiskSN9x(0,Result)
    else
    Result := '';
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
    Edit1.Text := getIDEHardDiskSN;
    end;end.
     
     
    以上代码在 Delphi 6+Win98,Delphi 6 + Win2000 下调试通过(2000下不需要ADMIN权限)。
    只适用于IDE硬盘,还有好象三星的某种硬盘无出厂序列号,当然也搞不定了:)
      

  4.   

    function tform1.GetHDSerialNumber: LongInt;    
        {$IFDEF WIN32}
        var 
          pdw : pDWord; 
          mc, fl : dword; 
        {$ENDIF} 
        begin 
          {$IfDef WIN32} 
          New(pdw); 
          GetVolumeInformation('c:\',nil,0,pdw,mc,fl,nil,0); 
          Result := pdw^;
          dispose(pdw); 
         {$ELSE}
          Result := GetWinFlags;
          {$ENDIF} 
        end;
        procedure TForm1.Button1Click(Sender: TObject);
        begin
          edit1.Text:=inttostr(gethdserialnumber);
        end;
      

  5.   

    function tform1.GetHDSerialNumber: LongInt; 
    ---------------------------------------------
    function GetHDSerialNumber: LongInt;
      

  6.   

    to Shiyl(云淡风清) 
    我要的是硬盘序列号,不是分区号
      

  7.   

    fhuibo(Sailor) 的方法看不懂,suiyuxing(秋水)得方法不能用在98上,bluezwt(蓝色天涯) 的方法在98和xp上可以,在2000下不行
      

  8.   

    斑竹用VC编写的DLL,可以获得硬盘的型号、序列号以及计算机 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