sectores reparar rapidamente que programa para gratis fisicamente externo duro disco dañados dañado como arranca delphi hardware delphi-7

delphi - rapidamente - programa para reparar disco duro gratis



en Delphi7, ¿cómo puedo recuperar el número de serie único del disco duro? (5)

Puede usar WMI (Windows Management Instrumentation) para obtener información relacionada con el hardware de Windows.

Existen dos clases de wmi que exponen una propiedad llamada SerialNumber que almacena the Number allocated by the manufacturer to identify the physical media. Estas clases son Win32_DiskDrive y Win32_PhysicalMedia acceder a la propiedad SerialNumber de estas clases, debes conocer el DeviceId del Disco, que es algo así como //./PHYSICALDRIVE0 . Otra forma es utilizar una clase de asociación que vincule la unidad física con la unidad lógica (C, D, E)

entonces debes encontrar este enlace previo para obtener el número de serie. la secuencia para encontrar esta asociación es así.

Win32_DiskPartition -> Win32_LogicalDiskToPartition -> Win32_DiskDrive

Nota 1 : la propiedad SerialNumber para la clase Win32_DiskDrive no existe en Windows Server 2003, Windows XP, Windows 2000 y Windows NT 4.0, por lo que la forma en que se habla de usar Windows Vista o Windows 7 funcionará bien para usted.

Nota 2 : El código no requiere la ejecución de una cuenta de administrador.

revisa este código

{$APPTYPE CONSOLE} uses SysUtils, ActiveX, ComObj, Variants; function GetDiskSerial(const Drive:AnsiChar):string; var FSWbemLocator : OLEVariant; objWMIService : OLEVariant; colDiskDrives : OLEVariant; colLogicalDisks: OLEVariant; colPartitions : OLEVariant; objDiskDrive : OLEVariant; objPartition : OLEVariant; objLogicalDisk : OLEVariant; oEnumDiskDrive : IEnumvariant; oEnumPartition : IEnumvariant; oEnumLogical : IEnumvariant; iValue : LongWord; DeviceID : string; begin; Result:=''''; FSWbemLocator := CreateOleObject(''WbemScripting.SWbemLocator''); objWMIService := FSWbemLocator.ConnectServer(''localhost'', ''root/CIMV2'', '''', ''''); //Connect to the WMI colDiskDrives := objWMIService.ExecQuery(''SELECT * FROM Win32_DiskDrive'',''WQL'',0); oEnumDiskDrive:= IUnknown(colDiskDrives._NewEnum) as IEnumVariant; while oEnumDiskDrive.Next(1, objDiskDrive, iValue) = 0 do begin DeviceID := StringReplace(objDiskDrive.DeviceID,''/',''//',[rfReplaceAll]); //Escape the `/` chars in the DeviceID value because the ''/' is a reserved character in WMI. colPartitions := objWMIService.ExecQuery(Format(''ASSOCIATORS OF {Win32_DiskDrive.DeviceID="%s"} WHERE AssocClass = Win32_DiskDriveToDiskPartition'',[DeviceID]));//link the Win32_DiskDrive class with the Win32_DiskDriveToDiskPartition class oEnumPartition := IUnknown(colPartitions._NewEnum) as IEnumVariant; while oEnumPartition.Next(1, objPartition, iValue) = 0 do begin colLogicalDisks := objWMIService.ExecQuery(''ASSOCIATORS OF {Win32_DiskPartition.DeviceID="''+objPartition.DeviceID+''"} WHERE AssocClass = Win32_LogicalDiskToPartition''); //link the Win32_DiskPartition class with theWin32_LogicalDiskToPartition class. oEnumLogical := IUnknown(colLogicalDisks._NewEnum) as IEnumVariant; while oEnumLogical.Next(1, objLogicalDisk, iValue) = 0 do begin if objLogicalDisk.DeviceID=(Drive+'':'') then //compare the device id begin Result:=objDiskDrive.SerialNumber; Exit; end; objLogicalDisk:=Unassigned; end; objPartition:=Unassigned; end; end; end; begin try CoInitialize(nil); try Writeln(GetDiskSerial(''C'')); Readln; finally CoUninitialize; end; except on E:Exception do begin Writeln(E.Classname, '':'', E.Message); Readln; end; end; end.

Hola, quiero recuperar el número de serie único de HDD (hardware). Uso algunas funciones pero en Windows Seven o Vista no funcionan correctamente debido a la administración correcta. ¿Es posible recuperarlo sin ejecutar como administrador?


Aquí hay otra traducción de DiskId32 de C ++ a Delphi por Victor Derevyanko

proyecto: http://code.google.com/p/dvsrc/

Debido a que el primer método (WithZeroRights) no funciona para mí, escribí otro para el método ReadIdeDriveAsScsiDriveInNT:

unit HDScsiInfo; interface uses Windows, SysUtils; const IDENTIFY_BUFFER_SIZE = 512; FILE_DEVICE_SCSI = $0000001b; IOCTL_SCSI_MINIPORT_IDENTIFY = ((FILE_DEVICE_SCSI shl 16) + $0501); IDE_ATA_IDENTIFY = $EC; // Returns ID sector for ATA. IOCTL_SCSI_MINIPORT = $0004D008; // see NTDDSCSI.H for definition type TDiskData = array [0..256-1] of DWORD; TDriveInfo = record ControllerType: Integer; //0 - primary, 1 - secondary, 2 - Tertiary, 3 - Quaternary DriveMS: Integer; //0 - master, 1 - slave DriveModelNumber: String; DriveSerialNumber: String; DriveControllerRevisionNumber: String; ControllerBufferSizeOnDrive: Int64; DriveType: String; //fixed or removable or unknown DriveSizeBytes: Int64; end; THDScsiInfo = class (TObject) private FDriveNumber: Byte; FFileHandle: Cardinal; FInfoAvailable: Boolean; FProductRevision: string; FSerialNumber: string; FControllerType: Integer; FDriveMS: Integer; FDriveModelNumber: string; FControllerBufferSizeOnDrive: Int64; FDriveType: string; FDriveSizeBytes: Int64; procedure ReadInfo; procedure SetDriveNumber(const Value: Byte); procedure PrintIdeInfo(DiskData: TDiskData); public constructor Create; property DriveNumber: Byte read FDriveNumber write SetDriveNumber; property ProductRevision: string read FProductRevision; property SerialNumber: string read FSerialNumber; property ControllerType: Integer read FControllerType; property DriveMS: Integer read FDriveMS; property DriveModelNumber: string read FDriveModelNumber; property ControllerBufferSizeOnDrive: Int64 read FControllerBufferSizeOnDrive; property DriveType: string read FDriveType; property DriveSizeBytes: Int64 read FDriveSizeBytes; function IsInfoAvailable: Boolean; end; implementation type SRB_IO_CONTROL = record HeaderLength: Cardinal; Signature: array [0..8-1] of Byte; Timeout: Cardinal; ControlCode: Cardinal; ReturnCode: Cardinal; Length: Cardinal; end; PSRB_IO_CONTROL = ^SRB_IO_CONTROL; DRIVERSTATUS = record bDriverError: Byte;// Error code from driver, or 0 if no error. bIDEStatus: Byte;// Contents of IDE Error register. // Only valid when bDriverError is SMART_IDE_ERROR. bReserved: array [0..1] of Byte;// Reserved for future expansion. dwReserved: array [0..1] of Longword;// Reserved for future expansion. end; SENDCMDOUTPARAMS = record cBufferSize: Longword;// Size of bBuffer in bytes DriverStatus: DRIVERSTATUS;// Driver status structure. bBuffer: array [0..0] of Byte;// Buffer of arbitrary length in which to store the data read from the // drive. end; IDEREGS = 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; SENDCMDINPARAMS = record cBufferSize: Longword;// Buffer size in bytes irDriveRegs: IDEREGS; // Structure with drive register values. bDriveNumber: Byte;// Physical drive number to send // command to (0,1,2,3). bReserved: array[0..2] of Byte;// Reserved for future expansion. dwReserved: array [0..3] of Longword;// For future use. bBuffer: array [0..0] of Byte;// Input buffer. //!TODO: this is array of single element end; PSENDCMDINPARAMS = ^SENDCMDINPARAMS; PSENDCMDOUTPARAMS = ^SENDCMDOUTPARAMS; IDSECTOR = record wGenConfig: Word; wNumCyls: Word; wReserved: Word; wNumHeads: Word; wBytesPerTrack: Word; wBytesPerSector: Word; wSectorsPerTrack: Word; wVendorUnique: array [0..3-1] of Word; sSerialNumber: array [0..20-1] of AnsiChar; wBufferType: Word; wBufferSize: Word; wECCSize: Word; sFirmwareRev: array [0..8-1] of AnsiChar; sModelNumber: array [0..40-1] of AnsiChar; wMoreVendorUnique: Word; wDoubleWordIO: Word; wCapabilities: Word; wReserved1: Word; wPIOTiming: Word; wDMATiming: Word; wBS: Word; wNumCurrentCyls: Word; wNumCurrentHeads: Word; wNumCurrentSectorsPerTrack: Word; ulCurrentSectorCapacity: Cardinal; wMultSectorStuff: Word; ulTotalAddressableSectors: Cardinal; wSingleWordDMA: Word; wMultiWordDMA: Word; bReserved: array [0..128-1] of Byte; end; PIDSECTOR = ^IDSECTOR; TArrayDriveInfo = array of TDriveInfo; type DeviceQuery = record HeaderLength: Cardinal; Signature: array [0..8-1] of Byte; Timeout: Cardinal; ControlCode: Cardinal; ReturnCode: Cardinal; Length: Cardinal; cBufferSize: Longword;// Buffer size in bytes irDriveRegs: IDEREGS; // Structure with drive register values. bDriveNumber: Byte;// Physical drive number to send bReserved: array[0..2] of Byte;// Reserved for future expansion. dwReserved: array [0..3] of Longword;// For future use. bBuffer: array [0..0] of Byte;// Input buffer. //!TODO: this is array of single element end; function ConvertToString (diskdata: TDiskData; firstIndex: Integer; lastIndex: Integer; buf: PAnsiChar): PAnsiChar; var index: Integer; position: Integer; begin position := 0; // each integer has two characters stored in it backwards for index := firstIndex to lastIndex do begin // get high byte for 1st character buf[position] := AnsiChar(Chr(diskdata [index] div 256)); inc(position); // get low byte for 2nd character buf [position] := AnsiChar(Chr(diskdata [index] mod 256)); inc(position); end; // end the string buf[position] := Chr(0); // cut off the trailing blanks index := position - 1; while (index >0) do begin // if not IsSpace(AnsiChar(buf[index])) if (AnsiChar(buf[index]) <> '' '') then break; buf [index] := Chr(0); dec(index); end; Result := buf; end; constructor THDScsiInfo.Create; begin inherited; SetDriveNumber(0); end; function THDScsiInfo.IsInfoAvailable: Boolean; begin Result := FInfoAvailable end; procedure THDScsiInfo.PrintIdeInfo (DiskData: TDiskData); var nSectors: Int64; serialNumber: array [0..1024-1] of AnsiChar; modelNumber: array [0..1024-1] of AnsiChar; revisionNumber: array [0..1024-1] of AnsiChar; begin // copy the hard drive serial number to the buffer ConvertToString (DiskData, 10, 19, @serialNumber); ConvertToString (DiskData, 27, 46, @modelNumber); ConvertToString (DiskData, 23, 26, @revisionNumber); FControllerType := FDriveNumber div 2; FDriveMS := FDriveNumber mod 2; FDriveModelNumber := modelNumber; FSerialNumber := serialNumber; FProductRevision := revisionNumber; FControllerBufferSizeOnDrive := DiskData [21] * 512; if ((DiskData [0] and $0080) <> 0) then FDriveType := ''Removable'' else if ((DiskData [0] and $0040) <> 0) then FDriveType := ''Fixed'' else FDriveType := ''Unknown''; // calculate size based on 28 bit or 48 bit addressing // 48 bit addressing is reflected by bit 10 of word 83 if ((DiskData[83] and $400) <> 0) then begin nSectors := DiskData[103] * Int64(65536) * Int64(65536) * Int64(65536) + DiskData[102] * Int64(65536) * Int64(65536) + DiskData[101] * Int64(65536) + DiskData[100]; end else begin nSectors := DiskData [61] * 65536 + DiskData [60]; end; // there are 512 bytes in a sector FDriveSizeBytes := nSectors * 512; end; procedure THDScsiInfo.ReadInfo; type DataArry = array [0..256-1] of WORD; PDataArray = ^DataArry; const SENDIDLENGTH = sizeof (SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE; var I: Integer; buffer: array [0..sizeof (SRB_IO_CONTROL) + SENDIDLENGTH - 1] of AnsiChar; dQuery: DeviceQuery; dummy: DWORD; pOut: PSENDCMDOUTPARAMS; pId: PIDSECTOR; DiskData: TDiskData; pIdSectorPtr: PWord; begin FInfoAvailable := False; FFileHandle := CreateFile (PChar(Format(''//./Scsi%d:'', [FDriveNumber])), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0); if (FFileHandle <> INVALID_HANDLE_VALUE) then begin ZeroMemory(@dQuery, SizeOf(dQuery)); dQuery.HeaderLength := sizeof (SRB_IO_CONTROL); dQuery.Timeout := 10000; dQuery.Length := SENDIDLENGTH; dQuery.ControlCode := IOCTL_SCSI_MINIPORT_IDENTIFY; StrLCopy(@dQuery.Signature, ''SCSIDISK'', 8); dQuery.irDriveRegs.bCommandReg := IDE_ATA_IDENTIFY; dQuery.bDriveNumber := FDriveNumber; if (DeviceIoControl (FFileHandle, IOCTL_SCSI_MINIPORT, @dQuery, SizeOf(dQuery), @buffer, sizeof (SRB_IO_CONTROL) + SENDIDLENGTH, dummy, nil)) then begin pOut := PSENDCMDOUTPARAMS(buffer + sizeof (SRB_IO_CONTROL)); //!TOCHECK pId := PIDSECTOR(@pOut^.bBuffer[0]); if (pId^.sModelNumber[0] <> Chr(0) ) then begin pIdSectorPtr := PWord(pId); for I := 0 to 256-1 do DiskData[I] := PDataArray(pIdSectorPtr)[I]; PrintIdeInfo (DiskData); FInfoAvailable := True; end; end; CloseHandle(FFileHandle); end; end; procedure THDScsiInfo.SetDriveNumber(const Value: Byte); begin FDriveNumber := Value; ReadInfo; end; end.

Uso de muestra:

procedure ReadIdeDriveAsScsiDriveInNT; var DriveNumber: Byte; HDDInfo: THDScsiInfo; begin HDDInfo := THDScsiInfo.Create(); try for DriveNumber := 0 to MAX_IDE_DRIVES - 1 do try HDDInfo.DriveNumber := DriveNumber; if HDDInfo.IsInfoAvailable then begin Writeln(''Available Drive: '', HDDInfo.DriveNumber); Writeln(''ControllerType: '', HDDInfo.ControllerType); Writeln(''DriveMS: '', HDDInfo.DriveMS); Writeln(''DriveModelNumber: '', HDDInfo.DriveModelNumber); Writeln(''ControllerBufferSizeOnDrive: '', HDDInfo.ControllerBufferSizeOnDrive); Writeln(''DriveType: '', HDDInfo.DriveType); Writeln(''DriveSizeBytes: '', HDDInfo.DriveSizeBytes); Writeln(''ProductRevision: '', HDDInfo.ProductRevision); Writeln(''SerialNumber: '', HDDInfo.SerialNumber); end; except on E: Exception do Writeln(Format(''DriveNumber %d, %s: %s'', [DriveNumber, E.ClassName, E.Message])); end; finally HDDInfo.Free; end; end; begin ReadIdeDriveAsScsiDriveInNT; Write(''Press <Enter>''); end.

Esto funciona muy bien con mi disco WD.


Publicando esto puramente para completar, y posiblemente satisfacer a los fanáticos del hard hardware interesados ​​o que mueren.

No tengo un compilador de Pascal a mi disposición para probar estas rutinas en los sistemas actuales de Windows, pero sí sé que este código funcionaba en la era de DOS. Tal vez todavía funciona desde una ventana de símbolo del sistema.

Código de Pascal:

uses Dos, Crt; type SerNoType = record case Integer of 0: (SerNo1, SerNo2: Word); 1: (SerNo: Longint); end; DiskSerNoInfoType = record Infolevel: Word; VolSerNo: SerNoType; VolLabel: array[1..11] of Char; FileSys: array[1..8] of Char; end; function HexDigit(N: Byte): Char; begin if N < 10 then HexDigit := Chr(Ord(''0'') + N) else HexDigit := Chr(Ord(''A'') + (N - 10)); end; function GetVolSerialNo(DriveNo: Byte): String; var ReturnArray: DiskSerNoInfoType; Regs: Registers; begin with Regs do begin AX := $440d; BL := DriveNo; CH := $08; CL := $66; DS := Seg(ReturnArray); DX := Ofs(ReturnArray); Intr($21, Regs); if (Flags and FCarry) <> 0 then GetVolSerialNo := '''' else with ReturnArray.VolSerNo do GetVolSerialNo := HexDigit(Hi(SerNo2) div 16) + HexDigit(Hi(SerNo2) mod 16) + HexDigit(Lo(SerNo2) div 16) + HexDigit(Lo(SerNo2) mod 16) + HexDigit(Hi(SerNo1) div 16) + HexDigit(Hi(SerNo1) mod 16) + HexDigit(Lo(SerNo1) div 16) + HexDigit(Lo(SerNo1) mod 16); end; end; procedure PutVolSerialNo(DriveNo: Byte; SerialNo: Longint); var ReturnArray: DiskSerNoInfoType; Regs: Registers; begin with Regs do begin AX := $440d; BL := DriveNo; CH := $08; CL := $66; DS := Seg(ReturnArray); DX := Ofs(ReturnArray); Intr($21, Regs); if (Flags and FCarry) = 0 then begin ReturnArray.VolSerNo.SerNo := SerialNo; AH := $69; BL := DriveNo; AL := $01; DS := Seg(ReturnArray); DX := Ofs(ReturnArray); Intr($21, Regs); end; end; end;

Por favor, no dude en actualizar esta respuesta para que funcione (si es posible) en Delphi.



Siguiendo los enlaces en los comentarios de la pregunta publicada por Sertac , encontré esta interesante pregunta de C ++ , donde Fredou respondió con un buen enlace a un ejemplo de proyecto de código que muestra cómo hacerlo en .NET , que a su vez se basó en un enlace al código Borland C ++ y artículo .

¡Lo bueno es que este código C ++ también funciona como usuario no administrador!

Ahora necesitas a alguien que te ayude a traducir este código C ++ a Delphi.

Editar : Encontré una unidad Delphi que hace esto por ti.

Escribí algunos ejemplos de uso:

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.

Unidad de 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.

Editar : las configuraciones de RAID requieren disposiciones especiales.

Por ejemplo, obtuve un sistema RAID con varias matrices RAID 5; solo se muestra el primero, y no muestra los números de serie de la unidad, sino el número de serie de la matriz RAID:

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

--jeroen