![]() |
Problem beim auslesen der Festplatten Seriennummer
Hallo,
ich schreibe gerade für uns ein Inventory Tool welches Hard- und Software der Geräte erfasst. Zur Identifizierung des Gerätes mit unseren Stammdaten wird eine Equipment Nummer benutzt, welche normalerweise bei der Installation auf dem Gerät hinterlegt wird. Nun kommt es leider vor das ein Gerät z.B. neu installiert wird ohne unser Wissen :wall: Aus diesem Grund wollte ich zur Identifizierung des Gerätes einen weiteren Parameter hinzuziehen, mit dem ich erkennen kann ob es ein bekanntes Gerät ist. Hier in der DP habe ich folgende Funktion gefunden zum auslesen der HDD Seriennummer. Sie funktioniert auch einwandfrei bei 90% unserer Geräte. Nur bei den restlichen bekomme ich beim anlegen des handle ein INVALID_HANDLE_VALUE zurück. Die Platten unterstützen aber definitiv S.M.A.R.T. und HD-Tune kann auch problemlos die Seriennummer auslesen. Hier mal die Funktion die ich benutze:
Delphi-Quellcode:
Eine Beispielplatte bei der es nicht geht ist z.B. eine Seagate Momentus 5400 ST98823A 80GB
function GetIdeSerialNumber ():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 : 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; 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 begin ShowMessage('Invalid Handle Value!'); Exit; end; 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; Hier mal der HD-Tune Auszug wo man eindeutig sieht das die Festplatte es normal kann: Zitat:
Delphi-Quellcode:
Ich wäre euch wirklich zu großem Dank verpflichtet :)
hDevice := CreateFile( '\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 ); Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
Schau doch mal hier im Forum bei dem aktuellen Thema MyPC nach, dass Programm kann die Seriennummern der Laufwerke auslesen.
![]() Stephan |
Re: Problem beim auslesen der Festplatten Seriennummer
Hallo,
UPDATE: wie ich herausfinden konnte sind Adminrechte nötig um dieses Handle zu bekommen :gruebel: Nur wieso brauche ich Adminrechte um die HD Serial auszulesen *grummel* Andere Programme wie HD-Tune können das auch ohne Adminrechte ... Also nochmal: kennt jemand einen Weg an die HD Serial zu kommen OHNE Adminrechte? @nahpets: Ich schau es mir mal an, aber das Programm läuft nicht bei mir unter win2k SP4. Es kommt nur der SplashScreen und danach nichts mehr. Ich schau mir mal den Source an. Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
Zitat:
Zitat:
|
Re: Problem beim auslesen der Festplatten Seriennummer
Zitat:
Zitat:
Ich google mir ja schon den ganzen Tag die Finger wund :/ Ich habe hier einen zugegebnermassen alten Artikel gefunden der diese Problematik mit einer fast identischen Funktion beschreibt. ![]() hier ist der handle aufruf aber
Delphi-Quellcode:
1. geht das gar nicht
// Get SCSI port handle
hDevice := CreateFile( '\\.\Scsi0:', // Note: '\\.\C:' requires administrative permissions. GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 ); 2. frage ich mich wieso er Scsi0 übergibt, aber oben in den Kommentaren schreibt das wäre für IDE Platten :gruebel: Wenn mir jemand eine alternative Möglichkeit zum finden der Seriennummer aufzeigen kann wäre ich sehr dankbar :angel: Die meisten Sachen man im Netz findet arbeiten ja mit GetVolumeInformation() .... was ja Schwachsinn ist weil das nur die Partionsnummer zurückliefert :( Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
Hallo,
meine weiteren Recherchen haben ergeben : Ich kenne bisher zwei Methoden an die HDD Serial zu kommen. 1. Die Methode die ich oben gepostet habe. Braucht leider admin Rechte unter win2k. 2. Per wmi, braucht keine admin rechte. Geht leider erst ab XP :( wir haben noch win2k 3. Es MUSS eine dritte Möglichkeit ohne Adminrechte geben.... HD Tune kriegt es hin, es gibt "BEZAHL" Komponenten für Delphi die das können ( ![]() Ja nur wie :?: Stundenlange Recherchen ahben bisher leider nichts ergebn :( Bin nach wie vor über jeden Tip dankbar. Ich denke es muss über S.M.A.R.T. gehen. Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
Hmm, mal ne andere Überlegung. WEnn du jetzt schon stundenlang googlest und testest, wäre es nicht sinnvoller (von der Kostenseite) die $19,95 bis $59,95 für die Komponente auszugeben?
|
Re: Problem beim auslesen der Festplatten Seriennummer
Hmm
Möglich wäre das *g Aber inzwischen hat mich der Ehrgeiz gepackt :D Ausserdem wenn man so argumentiert könnte ich auch einfach eine der hunderte guten Inventory Tools nehmen die es günstig oder kostenlos auf dem Markt gibt :) Gruß Oliver |
Re: Problem beim auslesen der Festplatten Seriennummer
Moin moin,
wie wär es mit GetVolumeInformation ![]()
Delphi-Quellcode:
Vielleicht hilft Dir das ja weiter ... (danke michael) :thumb:
function GetVolSNr:DWORD;
var dwSerialNumber : DWORD; dwMaxLength : DWORD; dwFlags : DWORD; begin GetVolumeInformation(PChar('C:\'), nil, 0, @dwSerialNumber, dwMaxLength,dwFlags, nil, 0); Result := dwSerialNumber; end; Gruss ascotlx |
Re: Problem beim auslesen der Festplatten Seriennummer
Hallo,
wie oben erwähnt liefert GetVolumeInfo nur die Seriennummer der logischen Partition. Welche untauglich ist da sie sich bei jeder Installation ändert. Gruß Oliver |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:11 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz