Avatar billede jensfudge Nybegynder
09. april 2003 - 12:48 Der 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.

/Jens
Avatar billede mortvader Nybegynder
09. april 2003 - 13:03 #1
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;
Avatar billede jensfudge Nybegynder
09. april 2003 - 13:12 #2
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.

/Jens
Avatar billede martinlind Nybegynder
09. april 2003 - 13:14 #3
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;

var hDevice : THandle;
  cbBytesReturned : DWORD;
  ptr : PChar;
  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 := ''; // 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;
Avatar billede borrisholt Novice
09. april 2003 - 13:41 #4
Hvis ikke det virker tror jeg at jeg kan grave noget andet frem.

Jens B
Avatar billede jensfudge Nybegynder
09. april 2003 - 13:51 #5
Øøø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.
Avatar billede martinlind Nybegynder
09. april 2003 - 14:00 #6
det er sku et godt spm. kan man ikke se det via bios'en ??
Avatar billede tolderlund Nybegynder
09. april 2003 - 14:05 #7
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.
Avatar billede jensfudge Nybegynder
09. april 2003 - 14:11 #8
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)
Avatar billede jensfudge Nybegynder
09. april 2003 - 14:14 #9
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...
Avatar billede martinlind Nybegynder
09. april 2003 - 14:16 #10
den checker på din windows version i koden

// Version Windows 95 OSR2, Windows 98

måske det har en betydning om det er en OSR2
Avatar billede jensfudge Nybegynder
09. april 2003 - 14:19 #11
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.
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester