Get Hard Drive Serial Number Delphi
Dear all, I'm trying to read serial no of the hard disk as a unique id of the machine. I tried the code as follows: class function TDeviceUtils.GetDeviceId: string; 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: LongInt; // 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.
Feb 01, 2015 I built the code segment by using Delphi XE 7 and tested it on my. I use this to get hard drive serial number. How to read the serial no of hard disk?
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 bDriverError: BYTE; bIDEStatus: BYTE; bReserved: array [0. 1] of BYTE; dwReserved: array [0. 1] of DWORD; end; TSendCmdOutParams = packed record // bBuffer的大小 cBufferSize: DWORD; DriverStatus: TDriverStatus; 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:= '; // '.
PhysicalDrive0 means the first drive, use '. PhysicalDrive1 ' for the second one, etc. HDevice:= CreateFile( '. PhysicalDrive0', 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 FillChar(SCIP, SizeOf(TSendCmdInParams) - 1, #0); FillChar(aIdOutCmd, SizeOf(aIdOutCmd), #0); cbBytesReturned:= 0; // Set up data structures for IDENTIFY command. Dear all, I'm trying to read serial no of the hard disk as a unique id of the machine. I tried the code as follows: class function TDeviceUtils.GetDeviceId: string; 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: LongInt; // 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 bDriverError: BYTE; bIDEStatus: BYTE; bReserved: array [0.
1] of BYTE; dwReserved: array [0. 1] of DWORD; end; TSendCmdOutParams = packed record // bBuffer??? CBufferSize: DWORD; DriverStatus: TDriverStatus; 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:= '; // '. PhysicalDrive0 means the first drive, use '. PhysicalDrive1 ' for the second one, etc. HDevice:= CreateFile( '.
PhysicalDrive0', 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 FillChar(SCIP, SizeOf(TSendCmdInParams) - 1, #0); FillChar(aIdOutCmd, SizeOf(aIdOutCmd), #0); cbBytesReturned:= 0; // Set up data structures for IDENTIFY command. Dear all, I'm trying to read serial no of the hard disk as a unique id of the machine. I tried the code as follows: class function TDeviceUtils.GetDeviceId: string; 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: LongInt; // 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 bDriverError: BYTE; bIDEStatus: BYTE; bReserved: array [0. 1] of BYTE; dwReserved: array [0. 1] of DWORD; end; TSendCmdOutParams = packed record // bBuffer??? CBufferSize: DWORD; DriverStatus: TDriverStatus; 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:= '; // '. PhysicalDrive0 means the first drive, use '. PhysicalDrive1 ' for the second one, etc. HDevice:= CreateFile( '.
PhysicalDrive0', 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 FillChar(SCIP, SizeOf(TSendCmdInParams) - 1, #0); FillChar(aIdOutCmd, SizeOf(aIdOutCmd), #0); cbBytesReturned:= 0; // Set up data structures for IDENTIFY command. George, Yes, it is for windows only. It is not perfect but can give you some clues. Each platform you will need to find a different approach. There is not such component that works on all platforms that I am aware of.
I am in need of that either. There is no HD on an android for example. You can use the build Serial number, but you will find that it is not always reliable.
Cheap chinese androids commonly repeats the same serials. Not sure how it works on apple platforms. So it is quite a work to find out.
Dear all, I'm trying to read serial no of the hard disk as a unique id of the machine. I tried the code as follows: class function TDeviceUtils.GetDeviceId: string; const IDENTIFY_BUFFER_SIZE = 512; type TIDERegs = packed record bFeaturesReg: BYTE; // Used for specifying SMART 'commands'. Discrete Math Epp Pdf Free. 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: LongInt; // 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 bDriverError: BYTE; bIDEStatus: BYTE; bReserved: array [0. 1] of BYTE; dwReserved: array [0. 1] of DWORD; end; TSendCmdOutParams = packed record // bBuffer???
CBufferSize: DWORD; DriverStatus: TDriverStatus; 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:= '; // '.
PhysicalDrive0 means the first drive, use '. PhysicalDrive1 ' for the second one, etc. HDevice:= CreateFile( '. PhysicalDrive0', 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 FillChar(SCIP, SizeOf(TSendCmdInParams) - 1, #0); FillChar(aIdOutCmd, SizeOf(aIdOutCmd), #0); cbBytesReturned:= 0; // Set up data structures for IDENTIFY command.
I'm trying to read serial no of the hard disk as a unique id of the machine. I tried the code as follows: Magenta Systems WMI and SMART Component from might help, however the SMART APIs were designed for PCs with only four IDE ATA drives and drives less than 128 gig, whereas SATA PCs may have six or more drives.
Also they only work with physical drives and not SCSI connected or RAID drives. There are Intel RST APIs that access the underlaying drives in PCs using Intel chipsets which Smartmontools supports, but it's complex C code and not easy to translate to Delphi. I'm trying to read serial no of the hard disk as a unique id of the machine. I tried the code as follows: Magenta Systems WMI and SMART Component from might help, however the SMART APIs were designed for PCs with only four IDE ATA drives and drives less than 128 gig, whereas SATA PCs may have six or more drives. Also they only work with physical drives and not SCSI connected or RAID drives.
There are Intel RST APIs that access the underlaying drives in PCs using Intel chipsets which Smartmontools supports, but it's complex C code and not easy to translate to Delphi.
Beside the required Pchar ->PAnsiChar fix, one problem that is easy to miss is System.Move('SCSIDISK', srbControl.Signature, 8); The string is passed in as a PChar to the move function. To fix it, I changed it to a typed const const kScsiDisk: AnsiString = 'SCSIDISK'; [.] System.Move(kScsiDisk, srbControl.Signature, 8); After fixing that, converting PChar ->PAnsiChar and Char ->AnsiChar, the code started returning a valid value on my system. There also seems to be an issue with the GetDeviceHandle. You are using '.
C:' to open the device, but from what I can tell, you should be using '. PhysicalDriveX' (Where X is the sequence of your drive). Then again, I'm not very familiar with querying device in this fashion so I might be missing something.