在Delphi7中,如何检索硬盘唯一序列号? [英] in Delphi7, How can I retrieve hard disk unique serial number?

查看:202
本文介绍了在Delphi7中,如何检索硬盘唯一序列号?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好
我想检索硬盘唯一(硬件)序列号。
我使用一些功能,但是在Windows 7或Vista中,由于管理员权限,它们无法正常工作。
是否可以以管理员身份运行?

解决方案

在问题评论中的链接 Sertac 发布,我发现这个有趣的C ++问题,其中 Fredou 回答了很好的链接到 codeproject示例显示如何在.NET中执行此操作,而后者又是基于链接到Borland C ++代码文章



很酷的是这个C ++代码作为非管理员你也需要一个人帮你把这个C ++代码翻译成Delphi。



编辑找到一个为您提供的Delphi单元。



我为此写了一些示例用法:

 程序DiskDriveSerialConsoleProject; 

{$ APPTYPE CONSOLE}

使用
Windows,
SysUtils,
hddinfo in'hddinfo.pas';

const
//假设主/辅,主/从拓扑的最大驱动数
MAX_IDE_DRIVES = 16;

程序ReadPhysicalDriveInNTWithZeroRights();
var
DriveNumber:Byte;
HDDInfo:THDDInfo;
begin
HDDInfo:= THDDInfo.Create();
尝试
为DriveNumber:= 0到MAX_IDE_DRIVES - 1 do
尝试
HDDInfo.DriveNumber:= DriveNumber;
如果HDDInfo.IsInfoAvailable然后
开始
Writeln('VendorId:',HDDInfo.VendorId);
Writeln('ProductId:',HDDInfo.ProductId);
Writeln('ProductRevision:',HDDInfo.ProductRevision);
Writeln('SerialNumber:',HDDInfo.SerialNumber);
Writeln('SerialNumberInt:',HDDInfo.SerialNumberInt);
Writeln('SerialNumberText:',HDDInfo.SerialNumberText);
结束
除了
在E:Exception do
Writeln(Format('DriveNumber%d,%s:%s',[DriveNumber,E.ClassName,E.Message]));
结束
finally
HDDInfo.Free;
结束
结束

begin
ReadPhysicalDriveInNTWithZeroRights;
写('按< Enter>');
Readln;
结束。

单位来自 http://www.delphipraxis.net/564756-post28.html

  // http: //www.delphipraxis.net/564756-post28.html 

unit hddinfo;

接口

使用Windows,SysUtils,Classes;

const
IOCTL_STORAGE_QUERY_PROPERTY = $ 2D1400;

type
THDDInfo = class(TObject)
private
FDriveNumber:Byte;
FFileHandle:红衣主教;
FInfoAvailable:Boolean;
FProductRevision:string;
FProductId:string;
FSerialNumber:string;
FVendorId:string;
procedure ReadInfo;
程序SetDriveNumber(const Value:Byte);
public
构造函数创建;
属性DriveNumber:字节读FDriveNumber写SetDriveNumber;
property VendorId:string read FVendorId;
property ProductId:string read FProductId;
property ProductRevision:string read FProductRevision;
属性SerialNumber:string read FSerialNumber;
函数SerialNumberInt:Cardinal;
函数SerialNumberText:string;
函数IsInfoAvailable:Boolean;
结束

实现

类型
STORAGE_PROPERTY_QUERY =打包记录
PropertyId:DWORD;
QueryType:DWORD;
附加参数:字节数组[0..3]
结束

STORAGE_DEVICE_DESCRIPTOR =打包记录
版本:ULONG;
尺寸:ULONG;
DeviceType:Byte;
DeviceTypeModifier:Byte;
RemovableMedia:Boolean;
CommandQueueing:Boolean;
VendorIdOffset:ULONG;
ProductIdOffset:ULONG;
ProductRevisionOffset:ULONG;
SerialNumberOffset:ULONG;
STORAGE_BUS_TYPE:DWORD;
RawPropertiesLength:ULONG;
RawDeviceProperties:字节数组[0..511];
结束

函数ByteToChar(const B:Byte):Char;
begin
结果:= Chr(B + $ 30)
end;

函数SerialNumberToCardinal(SerNum:String):Cardinal;
begin
HexToBin(PChar(SerNum)),PChar(@Result),SizeOf(Cardinal));
结束

函数SerialNumberToString(SerNum:String):String;
var
I,StrLen:整数;
对:string;
B:字节;
Ch:Char绝对B;

begin
结果:='';
StrLen:=长度(SerNum);

如果Odd(StrLen)然后退出;

I:= 1;

,而I< StrLen do
begin
Pair:= Copy(SerNum,I,2);
HexToBin(PChar(Pair)),PChar(@B),1);
结果:= Result + Chr(B);
Inc(I,2);
结束

I:= 1;

,而I<长度(结果)do
begin
Ch:= Result [I];
结果[I]:=结果[I + 1];
结果[I + 1]:= Ch;
Inc(I,2);
结束
结束

构造函数THddInfo.Create;
开始
继承;

SetDriveNumber(0);
结束

函数THDDInfo.IsInfoAvailable:Boolean;
begin
结果:= FInfoAvailable
end;

程序THDDInfo.ReadInfo;
type
PCharArray = ^ TCharArray;
TCharArray =数组[0..32767]的Char;

var
返回:Cardinal;
状态:LongBool;
PropQuery:STORAGE_PROPERTY_QUERY;
DeviceDescriptor:STORAGE_DEVICE_DESCRIPTOR;
PCh:PChar;

begin
FInfoAvailable:= False;
FProductRevision:='';
FProductId:='';
FSerialNumber:='';
FVendorId:='';

尝试
FFileHandle:= CreateFile(
PChar('\\.\PhysicalDrive'+ ByteToChar(FDriveNumber)),
0,
FILE_SHARE_READ或FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
0,
0
);

如果FFileHandle = INVALID_HANDLE_VALUE然后
RaiseLastOSError;

ZeroMemory(@PropQuery,SizeOf(PropQuery));
ZeroMemory(@DeviceDescriptor,SizeOf(DeviceDescriptor));

DeviceDescriptor.Size:= SizeOf(DeviceDescriptor);

状态:= DeviceIoControl(
FFileHandle,
IOCTL_STORAGE_QUERY_PROPERTY,
@PropQuery,
SizeOf(PropQuery),
@DeviceDescriptor,
DeviceDescriptor.Size,
返回,
nil
);

如果不是状态然后
RaiseLastOSError;

如果DeviceDescriptor.VendorIdOffset<> 0然后
begin
PCh:= @PCharArray(@DeviceDescriptor)^ [DeviceDescriptor.VendorIdOffset];
FVendorId:= PCh;
结束

如果DeviceDescriptor.ProductIdOffset<> 0然后
begin
PCh:= @PCharArray(@DeviceDescriptor)^ [DeviceDescriptor.ProductIdOffset];
FProductId:= PCh;
结束

如果DeviceDescriptor.ProductRevisionOffset<> 0 then
begin
PCh:= @PCharArray(@DeviceDescriptor)^ [DeviceDescriptor.ProductRevisionOffset];
FProductRevision:= PCh;
结束

如果DeviceDescriptor.SerialNumberOffset<> 0然后
begin
PCh:= @PCharArray(@DeviceDescriptor)^ [DeviceDescriptor.SerialNumberOffset];
FSerialNumber:= PCh;
结束

FInfoAvailable:= True;
finally
如果FFileHandle<> INVALID_HANDLE_VALUE然后
CloseHandle(FFileHandle);
结束
结束

函数THDDInfo.SerialNumberInt:Cardinal;
begin
结果:= 0;
if((IsInfoAvailable = True)和(FSerialNumber<>))然后结果:= SerialNumberToCardinal(FSerialNumber)
end;

函数THDDInfo.SerialNumberText:string;
begin
结果:='';
if((IsInfoAvailable = True)和(FSerialNumber<>))然后Result:= SerialNumberToString(FSerialNumber)
end;

procedure THDDInfo.SetDriveNumber(const Value:Byte);
begin
FDriveNumber:= Value;
ReadInfo;
结束

结束。

编辑 RAID配置需要特殊规定。 >



例如,我有一个具有多个RAID 5阵列的RAID系统;只有第一个显示,它不显示驱动器序列号,但是RAID阵列的序列号:

  VendorId :AMCC 
ProductId:9550SXU-16ML
ProductRevision:3.08
SerialNumber:006508296D6A2A00DE82
SerialNumberInt:688416000

- jeroen


Hi I want to retrieve HDD unique (hardware) serial number. I use some functions but in Windows Seven or Vista they don't work correctly because of admin right. Is it possible retrieve it without run as Administrator?

解决方案

Following the links in the question comments Sertac posted, I came across this interesting C++ question, where Fredou answered with a nice link to a codeproject example showing how to do this in .NET, which in turn was based on a link to Borland C++ code and article.

The cool thing is that this C++ code works as a non-administrator user too!

Now you need someone to help you translate this C++ code to Delphi.

Edit: Found a Delphi unit that does this for you.

I wrote some sample use for it:

program DiskDriveSerialConsoleProject;

{$APPTYPE CONSOLE}

uses
  Windows,
  SysUtils,
  hddinfo in 'hddinfo.pas';

const
  // Max number of drives assuming primary/secondary, master/slave topology
  MAX_IDE_DRIVES = 16;

procedure ReadPhysicalDriveInNTWithZeroRights ();
var
  DriveNumber: Byte;
  HDDInfo: THDDInfo;
begin
  HDDInfo := THDDInfo.Create();
  try
    for DriveNumber := 0 to MAX_IDE_DRIVES - 1 do
    try
      HDDInfo.DriveNumber := DriveNumber;
      if HDDInfo.IsInfoAvailable then
      begin
        Writeln('VendorId: ', HDDInfo.VendorId);
        Writeln('ProductId: ', HDDInfo.ProductId);
        Writeln('ProductRevision: ', HDDInfo.ProductRevision);
        Writeln('SerialNumber: ', HDDInfo.SerialNumber);
        Writeln('SerialNumberInt: ', HDDInfo.SerialNumberInt);
        Writeln('SerialNumberText: ', HDDInfo.SerialNumberText);
      end;
    except
      on E: Exception do
        Writeln(Format('DriveNumber %d, %s: %s', [DriveNumber, E.ClassName, E.Message]));
    end;
  finally
    HDDInfo.Free;
  end;
end;

begin
  ReadPhysicalDriveInNTWithZeroRights;
  Write('Press <Enter>');
  Readln;
end.

Unit from http://www.delphipraxis.net/564756-post28.html

// http://www.delphipraxis.net/564756-post28.html

unit hddinfo;

interface

uses Windows, SysUtils, Classes;

const
  IOCTL_STORAGE_QUERY_PROPERTY = $2D1400;

type
  THDDInfo = class (TObject)
  private
    FDriveNumber: Byte;
    FFileHandle: Cardinal;
    FInfoAvailable: Boolean;
    FProductRevision: string;
    FProductId: string;
    FSerialNumber: string;
    FVendorId: string;
    procedure ReadInfo;
    procedure SetDriveNumber(const Value: Byte);
  public
    constructor Create;
    property DriveNumber: Byte read FDriveNumber write SetDriveNumber;
    property VendorId: string read FVendorId;
    property ProductId: string read FProductId;
    property ProductRevision: string read FProductRevision;
    property SerialNumber: string read FSerialNumber;
    function SerialNumberInt: Cardinal;
    function SerialNumberText: string;
    function IsInfoAvailable: Boolean;
  end;

implementation

type
  STORAGE_PROPERTY_QUERY = packed record
    PropertyId: DWORD;
    QueryType: DWORD;
    AdditionalParameters: array[0..3] of Byte;
  end;

  STORAGE_DEVICE_DESCRIPTOR = packed record
    Version: ULONG;
    Size: ULONG;
    DeviceType: Byte;
    DeviceTypeModifier: Byte;
    RemovableMedia: Boolean;
    CommandQueueing: Boolean;
    VendorIdOffset: ULONG;
    ProductIdOffset: ULONG;
    ProductRevisionOffset: ULONG;
    SerialNumberOffset: ULONG;
    STORAGE_BUS_TYPE: DWORD;
    RawPropertiesLength: ULONG;
    RawDeviceProperties: array[0..511] of Byte;
  end;

function ByteToChar(const B: Byte): Char;
begin
  Result := Chr(B + $30)
end;

function SerialNumberToCardinal (SerNum: String): Cardinal;
begin
  HexToBin(PChar(SerNum), PChar(@Result), SizeOf(Cardinal));
end;

function SerialNumberToString(SerNum: String): String;
var
  I, StrLen: Integer;
  Pair: string;
  B: Byte;
  Ch: Char absolute B;

begin
  Result := '';
  StrLen := Length(SerNum);

  if Odd(StrLen) then Exit;

  I := 1;

  while I < StrLen do
  begin
    Pair := Copy (SerNum, I, 2);
    HexToBin(PChar(Pair), PChar(@B), 1);
    Result := Result + Chr(B);
    Inc(I, 2);
  end;

  I := 1;

  while I < Length(Result) do
  begin
    Ch := Result[I];
    Result[I] := Result[I + 1];
    Result[I + 1] := Ch;
    Inc(I, 2);
  end;
end;

constructor THddInfo.Create;
begin
  inherited;

  SetDriveNumber(0);
end;

function THDDInfo.IsInfoAvailable: Boolean;
begin
  Result := FInfoAvailable
end;

procedure THDDInfo.ReadInfo;
type
  PCharArray = ^TCharArray;
  TCharArray = array[0..32767] of Char;

var
  Returned: Cardinal;
  Status: LongBool;
  PropQuery: STORAGE_PROPERTY_QUERY;
  DeviceDescriptor: STORAGE_DEVICE_DESCRIPTOR;
  PCh: PChar;

begin
  FInfoAvailable := False;
  FProductRevision := '';
  FProductId := '';
  FSerialNumber := '';
  FVendorId := '';

  try
    FFileHandle := CreateFile(
                     PChar('\\.\PhysicalDrive' + ByteToChar(FDriveNumber)),
                     0,
                     FILE_SHARE_READ or FILE_SHARE_WRITE,
                     nil,
                     OPEN_EXISTING,
                     0,
                     0
                   );

    if FFileHandle = INVALID_HANDLE_VALUE then
      RaiseLastOSError;

    ZeroMemory(@PropQuery, SizeOf(PropQuery));
    ZeroMemory(@DeviceDescriptor, SizeOf(DeviceDescriptor));

    DeviceDescriptor.Size := SizeOf(DeviceDescriptor);

    Status := DeviceIoControl(
                FFileHandle,
                IOCTL_STORAGE_QUERY_PROPERTY,
                @PropQuery,
                SizeOf(PropQuery),
                @DeviceDescriptor,
                DeviceDescriptor.Size,
                Returned,
                nil
              );

    if not Status then
      RaiseLastOSError;

    if DeviceDescriptor.VendorIdOffset <> 0 then
    begin
      PCh := @PCharArray(@DeviceDescriptor)^[DeviceDescriptor.VendorIdOffset];
      FVendorId := PCh;
    end;

    if DeviceDescriptor.ProductIdOffset <> 0 then
    begin
      PCh := @PCharArray(@DeviceDescriptor)^[DeviceDescriptor.ProductIdOffset];
      FProductId := PCh;
    end;

    if DeviceDescriptor.ProductRevisionOffset <> 0 then
    begin
      PCh := @PCharArray(@DeviceDescriptor)^[DeviceDescriptor.ProductRevisionOffset];
      FProductRevision := PCh;
    end;

    if DeviceDescriptor.SerialNumberOffset <> 0 then
    begin
      PCh := @PCharArray(@DeviceDescriptor)^[DeviceDescriptor.SerialNumberOffset];
      FSerialNumber := PCh;
    end;

    FInfoAvailable := True;
  finally
    if FFileHandle <> INVALID_HANDLE_VALUE then
      CloseHandle(FFileHandle);
  end;
end;

function THDDInfo.SerialNumberInt: Cardinal;
begin
  Result := 0;
  if ((IsInfoAvailable = True) and (FSerialNumber <> '')) then Result := SerialNumberToCardinal(FSerialNumber)
end;

function THDDInfo.SerialNumberText: string;
begin
  Result := '';
  if ((IsInfoAvailable = True) and (FSerialNumber <> '')) then Result := SerialNumberToString(FSerialNumber)
end;

procedure THDDInfo.SetDriveNumber(const Value: Byte);
begin
  FDriveNumber := Value;
  ReadInfo;
end;

end.

Edit: RAID configurations require special provisions.

For instance, I got a RAID system with multiple RAID 5 array; only the first one displays, and it does not show the drive serial numbers, but the serial number of the RAID array:

VendorId: AMCC
ProductId: 9550SXU-16ML
ProductRevision: 3.08
SerialNumber: 006508296D6A2A00DE82
SerialNumberInt: 688416000

--jeroen

这篇关于在Delphi7中,如何检索硬盘唯一序列号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆