昨天我看了关于提取磁盘序列号的文章,可是我自己怎么使用时错误?
unit diver;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form1: TForm1;
  
implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);  {}
var
  SerialNum : pdword;      
  a, b : Dword;
  Buffer: array [0..255] of char;    //缓冲区
  begin
  if GetVolumeInformation('', Buffer, SizeOf(Buffer), SerialNum, b, a,
   nil, 0)then
   Edit1.Text:= IntToStr(SerialNum^)else
   Edit1.Text:='提取错误¡'
end;procedure TForm1.Button3Click(Sender: TObject);
begin
close;
end;end.
出现错误提示如下:
[Warning] diver.pas(40): Variable 'SerialNum' might not have been initialized
解决马上给分!!!谢谢,谢谢,毕业设计明天要交的!

解决方案 »

  1.   

    procedure TForm1.Button1Click(Sender: TObject);  {}
    var
      SerialNum : dword;     
      a, b : Dword;
      Buffer: array [0..255] of char;    //缓冲区
      begin
      if GetVolumeInformation('', Buffer, SizeOf(Buffer), @SerialNum, b, a, 
       nil, 0) then
       Edit1.Text:= IntToStr(SerialNum) else
       Edit1.Text:='提取错误¡'
    end;
      

  2.   

    procedure TForm1.Button1Click(Sender: Tobject);
    var
      SectorsPerCluster,  // holds the sectors per cluster
      BytesPerSector,     // holds the bytes per sector
      FreeClusters,       // holds the number of free clusters
      Clusters: DWORD;    // holds the total number of disk clusters
    begin
      {retrieve the disk space information}
      if GetDiskFreeSpace('C:\',SectorsPerCluster,BytesPerSector,                      FreeClusters,Clusters) then
      begin
        {display the disk space information}
        Panel2.Caption := IntToStr(SectorsPerCluster);
        Panel3.Caption := IntToStr(BytesPerSector);
        Panel4.Caption := IntToStr(FreeClusters);
        Panel5.Caption := IntToStr(Clusters);
        Panel6.Caption := IntToStr(FreeClusters*BytesPerSector*SectorsPerCluster);
        Panel7.Caption := IntToStr(Clusters*BytesPerSector*SectorsPerCluster);  end;
    end;
      

  3.   

    sysu:你那个好像不行啊 !
      

  4.   

    获取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/ --------------------------------------------------------------------------------
      

  5.   

    deluser:
       谢谢你,不过那好像不是磁盘序列号啊 !麻烦给解释下!小弟初学!
      

  6.   

    获取光盘序列号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.
      

  7.   

    许多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   // (不要忘记在复制后重新启动系统)  
      

  8.   

    谢谢!我只需获取一般IDE硬盘序列号就可以了!
      

  9.   

    呀!现在还把我给整糊涂了!那就是说现在我用优化大师看出来的磁盘序列号:“5EG1F66T”
    不能用GetVolumeInformation