09. april 2003 - 12:48Der er
10 kommentarer og 1 løsning
Serienummer på Harddisk
Er der nogen der kan fortælle mig (gerne med kodestump) hvordan man finder det fysiske serienummer på en vilkårlig harddisk. Det er selvfølgelig programmeringsmæssigt gennem Delphi jeg vil gøre det.
Jeg gør opmærksom på at det IKKE er det serienummer man tildeler harddisken ved formattering, idet dette nummer er på det logiske drev. Det er det fysiske drev jeg er ude efter.
I lang tid har samarbejdsbranchen fokuseret på at forbedre enhedsfunktioner – bedre kameraer, klarere lyd og smartere software. Men den virkelige forvandling handler ikke om funktioner.
function GetVolumeID(DriveChar: Char): String; var MaxFileNameLength, VolFlags, SerNum: DWord; begin if GetVolumeInformation(PChar(DriveChar + ':\'), nil, 0, @SerNum, MaxFileNameLength, VolFlags, nil, 0) then begin Result := IntToHex(SerNum,8); Insert('-', Result, 5); end else Result := ''; end;
Nejjj, hvor ærgerligt.... Jeg troede ellers at jeg havde fået forklaret ret præcist at jeg IKKE ER UDE EFTER DET LOGISKE DREVS ID, men DET FYSISKE. Din funktion kender jeg godt, og det giver mig det logiske drev.
ved ikke om det virker, har ikke delphi kørende, men du kan jo prøve
mortvader >> GetVolumeInformation - giver det nr der bliver tildelt ved format
Unfortunally it works for IDE harddisk only.
// Get first IDE harddisk serial number 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 // Error code from driver, or 0 if no error. bDriverError : Byte; // Contents of IDE Error register. Only valid when bDriverError is SMART_IDE_ERROR. bIDEStatus : Byte; bReserved : Array[0..1] of Byte; dwReserved : Array[0..1] of DWORD; end; TSendCmdOutParams = packed record // Size of bBuffer in bytes cBufferSize : DWORD; // Driver status structure. DriverStatus : TDriverStatus; // Buffer of arbitrary length in which to store the data read from the drive. bBuffer : Array[0..0] of BYTE; end;
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 := ''; // return empty string on error if SysUtils.Win32Platform=VER_PLATFORM_WIN32_NT then // Windows NT, Windows 2000 begin // warning! change name for other drives: ex.: second drive '\\.\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;
Øøøhhh.. Det lyder måske åndsvagt... Men hvordan checker jeg egentllig om det virker... (Typisk at testspeccen ikke er skrevet endnu...) Kan jeg gennem windows kotrolpanel eller lign checke ?? (læs hvordan dælen gør man det). Rutinen giver faktisk et svar. Som måske kan være gyldig. Nu mangler jeg bare at verificere det. Samt måske finde en rutine der kan med SCSI diske også, men det er ikke så vigtigt. De 100 point går til martin når jeg har fundet ud af at verificere det.
Jeg har lige prøvet koden under WinXP prof og fik resultatet E16L8T1E Det passer fint med det SN jeg kan se når jeg tager min Maxtor ud kigger på de mærkater der sidder på den.
hmmmmm... Jeg har testet rutinen på en XP, det gav et resultat. På en Win98 var resultatet blank... Den skulle gerne give noget uanset windows... (fra 98 opad er ok)
Tolderlund. Sååå virker dimsen måske på XP, men ikke på 98... hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 ); Skulle da ellers være for dette...
hDevice := CreateFile( '\\.\SMARTVSD', 0, 0, nil, CREATE_NEW, 0, 0 ); Jeg tilføjede lige lidt kode...
if hDevice=INVALID_HANDLE_VALUE then begin ShowMessage('invalid'); Exit; end;
Da jeg kørte dette på win98 viste den sq invalid...
Nå, Martin får de 100 point for det virker da på XP.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.