同标题。

解决方案 »

  1.   

    procedure TForm1.Button1Click(Sender: TObject);  
    var SerialNum : pdword; a, b : dword; Buffer : array [0..255] of char;  
    begin  
      if GetVolumeInformation('c:\', Buffer, SizeOf(Buffer), SerialNum, a, b, nil, 0) then Label1.Caption := IntToStr(SerialNum^); end;
      

  2.   

    忘了,不过dir就行,记得msdn里有篇如何改序列号的(曾经想过要改实验室90台机的vol c,结果ghost了事),用汇编的
      

  3.   

    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;
    这是取硬盘ID的,我的2K Server下可以工作
      

  4.   

    不用那么麻烦吧,这样绝对没问题(试过100块IBM T32的硬盘):
     
    function GetIDESN: Cardinal;
    Var
    cSN:Cardinal;
    MaxNameLength:Cardinal;
    FSFlag:Cardinal;
    begin
    GetVolumeInformation('C:\',nil,0,@cSN,MaxNameLength,FSFlag,nil,0);
    Result:=cSN;
    end;上面 goodloop(小志)的程序好像指针(SerialNum : pdword)没有分配空间,不知道会不会出问题。
      

  5.   

    swordsmith(贱客)
    获得的不是序列号,而是卷标
      

  6.   

    用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
      

  7.   

    你试试这个吧!取Ide硬盘序列号函数 
    作者:  评价:  内容说明:  
    来源:  --------------------------------------------------------------------------------function GetIdeDiskSerialNumber : String; 
    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 := ''; 
    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)); 
    end; 
    end; 在win2000下,d5 d6都通过  
      
      

  8.   

    用取序列号作为程序加密并不是完全可行的。有的IDE硬盘并不具有序列号,而SCSI硬盘更是没有序列号一说,我试过三块SCSI硬盘,都不能取得序列号,不过,如果软件是装在某一台固定的机器上的话,用这个方法还是很不错的。
      

  9.   

    //==============================================================================
    //获得硬盘序列号****************************************************************
    //==============================================================================
    function GetHardDiskSerial(Drive: string): string;
    var VolumeSerialNumber: DWORD;
        MaximumComponentLength: DWORD;
        FileSystemFlags: DWORD;
    begin
      if Drive[Length(Drive)]=':' then Drive := Drive + '\';
      GetVolumeInformation(PChar(Drive), nil, 0, @VolumeSerialNumber, MaximumComponentLength, FileSystemFlags, nil, 0);
      Result := IntToHex(HiWord(VolumeSerialNumber), 4) + '-' + IntToHex(LoWord(VolumeSerialNumber), 4);
    end;
      

  10.   

    要获取win98系统上的硬盘序列号,上面的方法都不行啊?
    有谁有解决之道。
      

  11.   

    的却,上面的方法,在Win98下不行的,2000/XP都可以
    // Version Windows 95 OSR2, Windows 98
        hDevice := CreateFile('\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0); 对于Win98,是无效句柄!Win98SE没有对象\\.\SMARTVSD的

    Up
      

  12.   

    //==============================================================================
    //获得硬盘序列号****************************************************************
    //==============================================================================
    function GetHardDiskSerial(Drive: string): string;
    var VolumeSerialNumber: DWORD;
        MaximumComponentLength: DWORD;
        FileSystemFlags: DWORD;
    begin
      if Drive[Length(Drive)]=':' then Drive := Drive + '\';
      GetVolumeInformation(PChar(Drive), nil, 0, @VolumeSerialNumber, MaximumComponentLength, FileSystemFlags, nil, 0);
      Result := IntToHex(HiWord(VolumeSerialNumber), 4) + '-' + IntToHex(LoWord(VolumeSerialNumber), 4);
    end;
      

  13.   

    如像realist(现实) 提供的方法可以,但不知在win95,winMe中是否可用?
      

  14.   

    98下不能取道硬盘序列号
    我也很想知道这个问题
    有知道的和我联系
    [email protected]
      

  15.   


    #include <windows.h>
    #include <stdio.h>WORD pw[256];static DWORD idt, int_idt;
    static DWORD Base;
    static WORD Entry;#pragma warning (disable:4035) 
    static int inp(WORD rdx)
    {
    _asm xor eax, eax
    _asm mov dx, rdx
    _asm in al, dx
    }static WORD inpw(WORD rdx)
    {
    _asm xor eax, eax
    _asm mov dx, rdx
    _asm in ax, dx
    }static void outp(WORD rdx, int ral)
    {
    _asm mov dx, rdx
    _asm mov eax, ral
    _asm out dx, al
    }static int WaitIde()
    {
    int al;while ((al=inp(0x1F7))>=0x80) ;
    return al;
    }static void ReadIDE()
    {
    int al;
    int i;WaitIde();
    outp(0x1F6,0xA0);
    al = WaitIde();
    if ((al&0x50)!=0x50) return;outp(0x1F6,0xA0);
    outp(0x1F7,0xEC);
    al = WaitIde();
    if ((al&0x58)!=0x58) return;for (i=0;i<256;i++) {
    pw[i] = inpw(0x1F0);
    }
    }static void __declspec( naked ) NowInRing0()
    {
    _asm {
    push ebp 
    mov ebp,espcall ReadIDEcli
    mov ebx, int_idt
    mov ax, Entry
    mov word ptr [ebx-4], ax
    mov eax, Base
    shr eax, 16 
    mov [ebx+2], ax
    sti
    leave 
    iretd
    }
    }void GetIDEInfo()
    {
    DWORD dwExcept;dwExcept = (DWORD)NowInRing0;_asm {
    mov eax, fs:[0]
    push eax 
    sidt [esp-02h] 
    pop ebx 
    mov idt, ebx
    add ebx, 0x1C
    mov int_idt, ebxmov eax, [ebx] 
    mov [Base], eax
    mov ax, [ebx-4] 
    mov [Entry], axcli
    mov esi, dwExcept
    push esi
    mov [ebx-4], si
    shr esi, 16 
    mov [ebx+2], si 
    pop esi
    stiint 3
    }
    }main()
    {
    char s[80];
    register i,j;GetIDEInfo();for (i=0,j=0;i<10;i++) {
    s[j++]=pw[10+i]>>8;
    s[j++]=pw[10+i]&0xFF;
    }
    s[j] = 0;printf("Serial=%s\n", s);return 0;
    }Win9X的代码有问题,详情如下。感谢这位大哥的指点。NowCan: 你的FOR 9x的代码有问题,读从盘要么死机、要么读不出,应该象BCB_FAN的代码那样根据是主盘还是从盘调整参数。你的有问题的代码如下
    static void ReadIDE()
    {
    int al;
    int i;WaitIde();
    outp(0x1F6,0xA0); <=========主盘是0xA0,从盘是0xB0,
    al = WaitIde();
    if ((al&0x50)!=0x50) return;outp(0x1F6,0xA0); <========= 但这里却不进行区分,直接使用0xA0
    outp(0x1F7,0xEC); <========= 这个也有可能有问题
    对于ATA设备,是0xEC,
    但对于ATAPI设备,则为0xA1
    al = WaitIde();
    if ((al&0x58)!=0x58) return;for (i=0;i<256;i++) {
    pw[i] = inpw(0x1F0);
    }