2010-11-27 2 views
3

Как я могу получить серийный номер производителя USB-накопителя в Delphi?Как получить серийный номер производителя USB-накопителя?

Я попытался это:

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; 

Но он не возвращает правильный результат!

+0

Вы хотите, чтобы серийный номер был присвоен окнами при форматировании жесткого диска или серийном номере производителя? – RRUZ 2010-11-27 15:57:15

+0

Сериал от производителя! – opc0de 2010-11-27 16:04:58

ответ

12

opc0de, в соответствии с вашими комментариями Я дам вам образец с использованием WMI.

Во-первых, код, который вы опубликовали (с использованием функции GetVolumeInformation), возвращает серийный номер, назначенный окнами при форматировании диска.

Хорошая новость в котором существуют два Wmi классов Wich предоставляет свойство под названием SerialNumber, которые хранят the Number allocated by the manufacturer to identify the physical media. эти классы являются Win32_DiskDrive и Win32_PhysicalMedia.

Теперь плохие новости, к сожалению, эти классы не связаны напрямую с буквой (C, D, E, F ...) логического диска, потому что вы должны позвонить другим классам wmi, чтобы найти ссылку между логическую букву драйвера и физический диск.

поэтому вы должны найти эту ссылку раньше, чтобы получить серийный номер. последовательность для поиска этой ассоциации такова.

Win32_DiskPartition ->Win32_LogicalDiskToPartition ->Win32_DiskDrive

это код, чтобы получить серийный номер USB, используя 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. 

Кстати, некоторое время назад я написал приложение под названием WMI Delphi Code Creator, который может помочь вам генерировать DELPHI код для доступа к информации системы с помощью WMI.

UPDATE

Некоторые драйверы дисков USB не обнажают производитель серийный номер на имущество Win32_DiskDrive.SerialNumber, поэтому в этом случае вы можете извлечь серийный номер из PnPDeviceID собственности.

Проверьте этот образец кода.

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

Вы можете попробовать компонент TDiskInfo from GLib, чтобы получить SERIALNUMBER.
Он не использует WMI, но в некоторой системе (типы дисков) не извлекается номер.
Попробуйте. Это бесплатно.

С уважением.

Смежные вопросы