2010-11-27 12 views
3

Comment puis-je récupérer le numéro de série du fabricant d'un lecteur flash USB dans Delphi?Comment obtenir le numéro de série du fabricant d'un lecteur flash USB?

J'ai essayé:

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; 

Mais il ne retourne pas un résultat correct!

+0

Voulez-vous le numéro de série assigné par Windows lorsqu'un disque dur est formaté ou le numéro de série du fabricant? – RRUZ

+0

La série du fabricant! – opc0de

+3

Le WMI a été créé pour faciliter l'accès au système d'information, y compris le matériel, Le WMI est l'outil parfait pour ce genre de tâche, car il est très simple à utiliser. Je ne sais pas quelle est votre motivation pour ne pas utiliser le WMI. pouvez-vous expliquer cela? – RRUZ

Répondre

12

opc0de, en fonction de vos commentaires Je vais vous donner un échantillon en utilisant le WMI.

Tout d'abord, le code que vous avez publié (à l'aide de la fonction GetVolumeInformation) renvoie le numéro de série attribué par Windows lorsque vous formatez un disque.

Les bonnes nouvelles sont qui existent deux classes WMI wich expose une propriété appelée SerialNumber qui stockent the Number allocated by the manufacturer to identify the physical media. ces classes sont Win32_DiskDrive et Win32_PhysicalMedia.

Maintenant les mauvaises nouvelles, malheureusement ces classes ne sont pas directement associées à la lettre (C, D, E, F ...) du disque logique, parce que vous devez appeler à une autre classe wmi pour trouver le lien entre la lettre de pilote logique et le lecteur physique. Vous devez donc trouver ce lien avant d'obtenir le numéro de série. la séquence pour trouver cette association est comme ça.

Win32_DiskPartition ->Win32_LogicalDiskToPartition ->Win32_DiskDrive

c'est le code pour obtenir le numéro de série d'un USB en utilisant la classe Win32_DiskDrive.

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. 

Par ailleurs il y a quelque temps que j'ai écrit une application appelée WMI Delphi Code Creator qui peut vous aider à générer du code delphi pour accéder au système d'information à l'aide du WMI.

MISE À JOUR

Certains pilotes des disques USB ne met pas le fabricant numéro de série sur la propriété Win32_DiskDrive.SerialNumber, ainsi de suite ce cas, vous pouvez extraire le numéro de série de la propriété PnPDeviceID.

Vérifiez cet exemple de code.

{$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

lors de l'exécution du code j'ai eu l'exception suivante: Invalid Interroger une idée pourquoi? – opc0de

+2

ok, c'est à cause de votre version WMI changer cette ligne 'colDiskDrives: = objWMIService.ExecQuery ('SELECT DeviceID, numéro de série de Win32_DiskDrive WHERE InterfaceType =" USB "', 'WQL', 0); 'à' colDiskDrives: = objWMIService.ExecQuery ('SELECT * FROM Win32_DiskDrive WHERE InterfaceType = "USB"', 'WQL', 0); ' – RRUZ

+0

Le code a été modifié pour être compatible avec les anciennes versions de WMI. – RRUZ

2

Vous pouvez essayer le composant TDiskInfo from GLib pour obtenir le SerialNumber.
Il n'utilise pas WMI, mais dans certains systèmes (types de disques) ne récupère pas le nombre.
Essayez-le. C'est gratuit.

Cordialement.