解决方法
在
Sertac的问题评论链接之后,我发现这个
interesting C++ question,Fredou回答了一个很好的链接到一个
codeproject example showing how to do this in .NET,这反过来是基于
link to Borland C++ code和
article.
很酷的是,this C++ code也是非管理员用户!
现在你需要一个人帮你把这个C代码翻译成Delphi.
编辑:找到一个为你做的这个Delphi单元.
我为此写了一些示例用法:
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.
单位从http://www.delphipraxis.net/564756-post28.html
// http://www.delphipraxis.net/564756-post28.html unit hddinfo; interface uses Windows,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)),FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,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.
编辑:RAID配置需要特殊规定.
例如,我有一个具有多个RAID 5阵列的RAID系统;只有第一个显示,并且不显示驱动器序列号,但是RAID阵列的序列号:
VendorId: AMCC ProductId: 9550SXU-16ML ProductRevision: 3.08 SerialNumber: 006508296D6A2A00DE82 SerialNumberInt: 688416000
–jeroen