2010-11-27 2 views
3

Wie kann ich den Hersteller Seriennummer eines USB-Flash-Laufwerk in Delphi abrufen?Wie bekomme ich die Hersteller-Seriennummer eines USB-Sticks?

Ich habe dies versucht:

function GetDiskVolSerialID(ADriveName: Char): Cardinal; 
var 
    DiskDrive: string; 
    FileSystemFlags: DWORD; 
    VolumeSerialNumber: DWORD; 
    MaximumComponentLength: DWORD; 
begin 
    DiskDrive := ADriveName + ':\'; 
    GetVolumeInformation(PChar(DiskDrive), 
         nil, 
         0, 
         @VolumeSerialNumber, 
         MaximumComponentLength, 
         FileSystemFlags, 
         nil, 
         0); 
    Result := VolumeSerialNumber; 
end; 

Aber es funktioniert nicht richtig Ergebnis zurück!

+0

Möchten Sie die Seriennummer von Windows zugewiesen bekommen, wenn eine Festplatte formatiert ist oder die Seriennummer vom Hersteller? – RRUZ

+0

Die Seriennummer vom Hersteller! – opc0de

+3

Die WMI wurde geschaffen, um den Zugriff auf Informationssystem einschließlich der Hardware zu erleichtern. Die WMI ist das perfekte Werkzeug für diese Art von Aufgabe, weil sie sehr einfach zu bedienen ist. Ich weiß nicht, was deine Motivation ist, das WMI nicht zu benutzen. kannst du das erklären? – RRUZ

Antwort

12

opc0de, nach Ihren Kommentaren Ich gebe Ihnen eine Probe mit dem WMI.

Zuerst den Code, den Sie (mit der GetVolumeInformation-Funktion) gebucht haben, geben Sie die Seriennummer von Windows zugewiesen, wenn Sie eine Festplatte formatieren.

Die gute Nachricht sind die zwei wmi Klassen existieren wich macht eine Eigenschaft namens SerialNumber die the Number allocated by the manufacturer to identify the physical media. speichern diese Klassen sind Win32_DiskDrive und Win32_PhysicalMedia.

Nun die schlechten Nachrichten, leider ist diese Klasse nicht direkt mit dem Buchstaben (C, D, E, F ...) der logischen Festplatte verbunden, denn das müssen Sie zu einem anderen WMI-Klassen aufrufen, um die Verbindung zwischen zu finden der logische Treiberbuchstabe und das physische Laufwerk.

so müssen Sie diesen Link vorherigen finden die Seriennummer zu erhalten. Die Reihenfolge, um diese Assoziation zu finden, ist so.

Win32_DiskPartition ->Win32_LogicalDiskToPartition ->Win32_DiskDrive

dies ist der Code, um die Seriennummer eines USB mit der Win32_DiskDrive Klasse zu erhalten.

program GetWMI_Info; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils, 
    StrUtils, 
    ActiveX, 
    ComObj, 
    Variants; 

function VarArrayToStr(const vArray: variant): string; 

    function _VarToStr(const V: variant): string; 
    var 
    Vt: integer; 
    begin 
    Vt := VarType(V); 
     case Vt of 
      varSmallint, 
      varInteger : Result := IntToStr(integer(V)); 
      varSingle, 
      varDouble, 
      varCurrency : Result := FloatToStr(Double(V)); 
      varDate  : Result := VarToStr(V); 
      varOleStr : Result := WideString(V); 
      varBoolean : Result := VarToStr(V); 
      varVariant : Result := VarToStr(Variant(V)); 
      varByte  : Result := char(byte(V)); 
      varString : Result := String(V); 
      varArray : Result := VarArrayToStr(Variant(V)); 
     end; 
    end; 

var 
i : integer; 
begin 
    Result := '['; 
    if (VarType(vArray) and VarArray)=0 then 
     Result := _VarToStr(vArray) 
    else 
    for i := VarArrayLowBound(vArray, 1) to VarArrayHighBound(vArray, 1) do 
    if i=VarArrayLowBound(vArray, 1) then 
     Result := Result+_VarToStr(vArray[i]) 
    else 
     Result := Result+'|'+_VarToStr(vArray[i]); 

    Result:=Result+']'; 
end; 

function VarStrNull(const V:OleVariant):string; //avoid problems with null strings 
begin 
    Result:=''; 
    if not VarIsNull(V) then 
    begin 
    if VarIsArray(V) then 
     Result:=VarArrayToStr(V) 
    else 
    Result:=VarToStr(V); 
    end; 
end; 


function GetWMIObject(const objectName: String): IDispatch; //create the Wmi instance 
var 
    chEaten: Integer; 
    BindCtx: IBindCtx; 
    Moniker: IMoniker; 
begin 
    OleCheck(CreateBindCtx(0, bindCtx)); 
    OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker)); 
    OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result)); 
end; 



function GetUsbDriveSerial(const Drive:AnsiChar):string; 
var 
    objWMIService : OLEVariant; 
    colDiskDrives : OLEVariant; 
    colLogicalDisks: OLEVariant; 
    colPartitions : OLEVariant; 
    objDiskDrive : OLEVariant; 
    objPartition : OLEVariant; 
    objLogicalDisk : OLEVariant; 
    oEnumDiskDrive : IEnumvariant; 
    oEnumPartition : IEnumvariant; 
    oEnumLogical : IEnumvariant; 
    iValue   : LongWord; 
    DeviceID  : string; 
begin; 
    Result:=''; 
    objWMIService := GetWMIObject('winmgmts:\\localhost\root\CIMV2'); //Connect to the WMI 
    //colDiskDrives := objWMIService.ExecQuery('SELECT DeviceID,SerialNumber FROM Win32_DiskDrive WHERE InterfaceType="USB"','WQL',0); 
    colDiskDrives := objWMIService.ExecQuery('SELECT * FROM Win32_DiskDrive WHERE InterfaceType="USB"','WQL',0); 
    oEnumDiskDrive:= IUnknown(colDiskDrives._NewEnum) as IEnumVariant; 
    while oEnumDiskDrive.Next(1, objDiskDrive, iValue) = 0 do 
    begin 
    DeviceID  := StringReplace(VarStrNull(objDiskDrive.DeviceID),'\','\\',[rfReplaceAll]); //Escape the `\` chars in the DeviceID value because the '\' is a reserved character in WMI. 
    colPartitions := objWMIService.ExecQuery(Format('ASSOCIATORS OF {Win32_DiskDrive.DeviceID="%s"} WHERE AssocClass = Win32_DiskDriveToDiskPartition',[DeviceID]));//link the Win32_DiskDrive class with the Win32_DiskDriveToDiskPartition class 
    oEnumPartition := IUnknown(colPartitions._NewEnum) as IEnumVariant; 
     while oEnumPartition.Next(1, objPartition, iValue) = 0 do 
     begin 
      colLogicalDisks := objWMIService.ExecQuery('ASSOCIATORS OF {Win32_DiskPartition.DeviceID="'+VarStrNull(objPartition.DeviceID)+'"} WHERE AssocClass = Win32_LogicalDiskToPartition'); //link the Win32_DiskPartition class with theWin32_LogicalDiskToPartition class. 
      oEnumLogical := IUnknown(colLogicalDisks._NewEnum) as IEnumVariant; 
       while oEnumLogical.Next(1, objLogicalDisk, iValue) = 0 do 
       if VarStrNull(objLogicalDisk.DeviceID)=(Drive+':') then //compare the device id 
       begin 
        Result:=VarStrNull(objDiskDrive.SerialNumber); 
        Exit; 
       end; 
     end; 
    end; 
end; 

begin 
try 
    CoInitialize(nil); 
    try 
     Writeln(GetUsbDriveSerial('F')); 
     Readln; 
    finally 
     CoUninitialize; 
    end; 
except 
    on E:Exception do 
    begin 
     Writeln(E.Classname, ':', E.Message); 
     Readln; 
    end; 
    end; 
end. 

Durch die Art und Weise vor einiger Zeit schrieb ich eine Anwendung namens WMI Delphi Code Creator, die Sie delphi-Code generieren helfen kann, die Systeminformationen mit dem WMI zuzugreifen.

UPDATE

Einige Treiber der USB-Laufwerke nicht an die Hersteller Seriennummer auf der Win32_DiskDrive.SerialNumber Eigenschaft aussetzen, so auf diesem Fällen Sie die Seriennummer aus der PnPDeviceID Eigenschaft extrahieren können.

prüft diesen Beispielcode.

{$APPTYPE CONSOLE} 

uses 
    SysUtils, 
    StrUtils, 
    ActiveX, 
    ComObj, 
    Variants; 


function VarStrNull(const V:OleVariant):string; //avoid issues with null variants 
begin 
    Result:=''; 
    if not VarIsNull(V) then 
    Result:=VarToStr(V); 
end; 


function GetUsbDriveSerial(const Drive:AnsiChar):string; 
var 
FSWbemLocator : OleVariant; 
    objWMIService : OLEVariant; 
    colDiskDrives : OLEVariant; 
    colLogicalDisks: OLEVariant; 
    colPartitions : OLEVariant; 
    objDiskDrive : OLEVariant; 
    objPartition : OLEVariant; 
    objLogicalDisk : OLEVariant; 
    oEnumDiskDrive : IEnumvariant; 
    oEnumPartition : IEnumvariant; 
    oEnumLogical : IEnumvariant; 
    iValue   : LongWord; 
    DeviceID  : string; 
begin; 
    Result:=''; 
    FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator'); 
    objWMIService := FSWbemLocator.ConnectServer('.', 'root\CIMV2', '', ''); 
    colDiskDrives := objWMIService.ExecQuery('SELECT * FROM Win32_DiskDrive WHERE InterfaceType="USB"','WQL',0); 
    oEnumDiskDrive:= IUnknown(colDiskDrives._NewEnum) as IEnumVariant; 
    while oEnumDiskDrive.Next(1, objDiskDrive, iValue) = 0 do 
    begin 
    DeviceID  := StringReplace(VarStrNull(objDiskDrive.DeviceID),'\','\\',[rfReplaceAll]); //Escape the `\` chars in the DeviceID value because the '\' is a reserved character in WMI. 
    colPartitions := objWMIService.ExecQuery(Format('ASSOCIATORS OF {Win32_DiskDrive.DeviceID="%s"} WHERE AssocClass = Win32_DiskDriveToDiskPartition',[DeviceID]));//link the Win32_DiskDrive class with the Win32_DiskDriveToDiskPartition class 
    oEnumPartition := IUnknown(colPartitions._NewEnum) as IEnumVariant; 
     while oEnumPartition.Next(1, objPartition, iValue) = 0 do 
     begin 
     colLogicalDisks := objWMIService.ExecQuery('ASSOCIATORS OF {Win32_DiskPartition.DeviceID="'+VarStrNull(objPartition.DeviceID)+'"} WHERE AssocClass = Win32_LogicalDiskToPartition'); //link the Win32_DiskPartition class with theWin32_LogicalDiskToPartition class. 
     oEnumLogical := IUnknown(colLogicalDisks._NewEnum) as IEnumVariant; 
      while oEnumLogical.Next(1, objLogicalDisk, iValue) = 0 do 
      begin 
      if SameText(VarStrNull(objLogicalDisk.DeviceID),Drive+':') then //compare the device id 
      begin 
       Result:=VarStrNull(objDiskDrive.PnPDeviceID); 
       if AnsiStartsText('USBSTOR', Result) then 
       begin 
       iValue:=LastDelimiter('\', Result); 
       Result:=Copy(Result, iValue+1, Length(Result)); 
       end; 
       objLogicalDisk:=Unassigned; 
       Exit; 
      end; 
      objLogicalDisk:=Unassigned; 
      end; 
      objPartition:=Unassigned; 
     end; 
     objDiskDrive:=Unassigned; 
    end; 
end; 

begin 
try 
    CoInitialize(nil); 
    try 
     Writeln(GetUsbDriveSerial('F')); 
     Readln; 
    finally 
     CoUninitialize; 
    end; 
except 
    on E:Exception do 
    begin 
     Writeln(E.Classname, ':', E.Message); 
     Readln; 
    end; 
    end; 
end. 
+0

während der Code ausgeführt wurde, trat ich die folgende Ausnahme auf: Ungültige Abfrage keine Idee warum? – opc0de

+2

ok, das ist wegen Ihrer WMI-Version ändern Sie diese Zeile 'colDiskDrives: = objWMIService.ExecQuery ('SELECT DeviceID, SerialNumber FROM Win32_DiskDrive WHERE InterfaceType =" USB "', 'WQL', 0); 'zu' colDiskDrives: = objWMIService.ExecQuery ('SELECT * FROM Win32_DiskDrive WHERE InterfaceType = "USB"', 'WQL', 0); ' – RRUZ

+0

Der Code wurde bearbeitet, um mit alten Versionen von WMI kompatibel zu sein. – RRUZ

2

können Sie die Komponente versuchen TDiskInfo from GLib serial zu bekommen.
WMI wird nicht verwendet, aber in einigen Systemen (Plattentypen) wird die Nummer nicht abgerufen.
Probieren Sie es. Es ist kostenlos.

Grüße.