AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Problem beim auslesen der Festplatten Seriennummer

Problem beim auslesen der Festplatten Seriennummer

Ein Thema von dbdeath74 · begonnen am 20. Okt 2006 · letzter Beitrag vom 26. Sep 2015
Antwort Antwort
Seite 1 von 4  1 23     Letzte » 
dbdeath74

Registriert seit: 30. Aug 2005
53 Beiträge
 
#1

Problem beim auslesen der Festplatten Seriennummer

  Alt 20. Okt 2006, 11:12
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
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:
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;
Eine Beispielplatte bei der es nicht geht ist z.B. eine Seagate Momentus 5400 ST98823A 80GB
Hier mal der HD-Tune Auszug wo man eindeutig sieht das die Festplatte es normal kann:

Zitat:
HD Tune: ST98823A Information

Firmware version : 3.05
Serial number : 5PK0SKH2
Capacity : 74.5 GB (~80.0 GB)
Buffer size : 8192 KB
Standard : ATA/ATAPI-6
Supported mode : UDMA Mode 5 (Ultra ATA/100)
Current mode : UDMA Mode 5 (Ultra ATA/100)

S.M.A.R.T : yes
48-bit Address : no
Read Look-Ahead : yes
Write Cache : yes
Host Protected Area : no
Device Configuration Overlay : yes
Automatic Acoustic Management: no
Power Management : yes
Advanced Power Management : yes
Power-up in Standby : no
Security Mode : yes
Firmware Upgradable : yes
Kennt vielleicht jemand eine bessere/andere Methode an die HDD-Serial zu kommen? Oder kann mir sagen wieso ich ein INVALID_HANDLE_VALUE von Windows zurückbekomme beim Aufruf:
Delphi-Quellcode:
hDevice := CreateFile( '\\.\PhysicalDrive0', GENERIC_READ or GENERIC_WRITE,
        FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0 );
Ich wäre euch wirklich zu großem Dank verpflichtet

Gruß Oliver
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#2

Re: Problem beim auslesen der Festplatten Seriennummer

  Alt 20. Okt 2006, 13:11
Schau doch mal hier im Forum bei dem aktuellen Thema MyPC nach, dass Programm kann die Seriennummern der Laufwerke auslesen.

MyPC-Thread

Stephan
  Mit Zitat antworten Zitat
dbdeath74

Registriert seit: 30. Aug 2005
53 Beiträge
 
#3

Re: Problem beim auslesen der Festplatten Seriennummer

  Alt 20. Okt 2006, 14:22
Hallo,

UPDATE: wie ich herausfinden konnte sind Adminrechte nötig um dieses Handle zu bekommen

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
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#4

Re: Problem beim auslesen der Festplatten Seriennummer

  Alt 20. Okt 2006, 14:43
Zitat von dbdeath74:
Nur wieso brauche ich Adminrechte um die HD Serial auszulesen *grummel*
Du holst dir ein Handle zum direkten Zugriff auf die Festplatte und kannst somit von hinten auf die Festplatte, die Partitionen und Daten zugreifen. Damit könntest du die Daten zerschiessen - und das sollte jedes Programm mit User Rechten können - sicher?

Zitat von dbdeath74:
Andere Programme wie HD-Tune können das auch ohne Adminrechte ...
Die besorgen sich für diese Aktion die Rechte bzw. lösen es über einen anderen Weg.
  Mit Zitat antworten Zitat
dbdeath74

Registriert seit: 30. Aug 2005
53 Beiträge
 
#5

Re: Problem beim auslesen der Festplatten Seriennummer

  Alt 20. Okt 2006, 15:22
Zitat von Muetze1:
Du holst dir ein Handle zum direkten Zugriff auf die Festplatte und kannst somit von hinten auf die Festplatte, die Partitionen und Daten zugreifen. Damit könntest du die Daten zerschiessen - und das sollte jedes Programm mit User Rechten können - sicher?
Natürlich nicht. Beim genaueren Nachdenken warum es nur mit Admin Rechten geht ist mir dies auch klar geworden

Zitat von Muetze1:
Die besorgen sich für diese Aktion die Rechte bzw. lösen es über einen anderen Weg.
Ja und genau das interessiert mich wie machen die das ?
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.
IDE harddisk serial
hier ist der handle aufruf aber
Delphi-Quellcode:
// 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 );
1. geht das gar nicht
2. frage ich mich wieso er Scsi0 übergibt, aber oben in den Kommentaren schreibt das wäre für IDE Platten

Wenn mir jemand eine alternative Möglichkeit zum finden der Seriennummer aufzeigen kann wäre ich sehr dankbar
Die meisten Sachen man im Netz findet arbeiten ja mit GetVolumeInformation() .... was ja Schwachsinn ist weil das nur die Partionsnummer zurückliefert

Gruß Oliver
  Mit Zitat antworten Zitat
dbdeath74

Registriert seit: 30. Aug 2005
53 Beiträge
 
#6

Re: Problem beim auslesen der Festplatten Seriennummer

  Alt 23. Okt 2006, 10:20
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 ( Delpji-Komponente)
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
  Mit Zitat antworten Zitat
Thanatos81
(Gast)

n/a Beiträge
 
#7

Re: Problem beim auslesen der Festplatten Seriennummer

  Alt 23. Okt 2006, 10:41
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?
  Mit Zitat antworten Zitat
dbdeath74

Registriert seit: 30. Aug 2005
53 Beiträge
 
#8

Re: Problem beim auslesen der Festplatten Seriennummer

  Alt 23. Okt 2006, 10:43
Hmm

Möglich wäre das *g
Aber inzwischen hat mich der Ehrgeiz gepackt

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
  Mit Zitat antworten Zitat
Benutzerbild von ascotlx
ascotlx

Registriert seit: 8. Mär 2005
Ort: Hamburg
97 Beiträge
 
Delphi 7 Professional
 
#9

Re: Problem beim auslesen der Festplatten Seriennummer

  Alt 23. Okt 2006, 11:07
Moin moin,

wie wär es mit GetVolumeInformation DP-Artikel . Ein Freund hat das mal so gemacht ....

Delphi-Quellcode:
function GetVolSNr:DWORD;
var
    dwSerialNumber : DWORD;
    dwMaxLength : DWORD;
    dwFlags : DWORD;

begin
    GetVolumeInformation(PChar('C:\'), nil, 0,
                         @dwSerialNumber, dwMaxLength,dwFlags,
                          nil, 0);
    Result := dwSerialNumber;
end;
Vielleicht hilft Dir das ja weiter ... (danke michael)

Gruss

ascotlx
  Mit Zitat antworten Zitat
dbdeath74

Registriert seit: 30. Aug 2005
53 Beiträge
 
#10

Re: Problem beim auslesen der Festplatten Seriennummer

  Alt 23. Okt 2006, 11:27
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
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:54 Uhr.
Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf