Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>opc0de, <strong>according to your comments</strong> i will give you a sample using the WMI. </p> <p>First, the code which you posted (using the <a href="http://msdn.microsoft.com/en-us/library/aa364993%28VS.85%29.aspx"><code>GetVolumeInformation</code></a> function) return the serial number assigned by windows when you format a disk.</p> <p>The good news are which exist two wmi classes wich exposes a property called <code>SerialNumber</code> which store <code>the Number allocated by the manufacturer to identify the physical media.</code> these classes are <a href="http://msdn.microsoft.com/en-us/library/aa394132%28VS.85%29.aspx"><code>Win32_DiskDrive</code></a> and <a href="http://msdn.microsoft.com/en-us/library/aa394346%28v=VS.85%29.aspx"><code>Win32_PhysicalMedia</code></a>.</p> <p>Now the bad news, unfortunately this classes is not associated directly with the letter (C,D,E,F...) of the logical disk, because that you must call to another wmi classes to find the link between the logical driver letter and the Physical drive.</p> <p>so you must find this link previous to obtain the serial number. the sequence to find this association is like this.</p> <p><a href="http://msdn.microsoft.com/en-us/library/aa394135%28VS.85%29.aspx"><code>Win32_DiskPartition</code></a> -> <a href="http://msdn.microsoft.com/en-us/library/aa394175%28VS.85%29.aspx"><code>Win32_LogicalDiskToPartition</code></a> -> <a href="http://msdn.microsoft.com/en-us/library/aa394132%28VS.85%29.aspx"><code>Win32_DiskDrive</code></a></p> <p>this is the code to obtain the serial number of a usb using the <a href="http://msdn.microsoft.com/en-us/library/aa394132%28VS.85%29.aspx"><code>Win32_DiskDrive</code></a> class.</p> <pre><code>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. </code></pre> <p>By the way some time ago i wrote an application called <a href="http://theroadtodelphi.wordpress.com/wmi-delphi-code-creator/"><em>WMI Delphi Code Creator</em></a> which can help you to generate delphi code to access the system info using the WMI.</p> <p><strong>UPDATE</strong></p> <p>Some drivers of the USB disks does not expose the manufacturer serial number on the Win32_DiskDrive.SerialNumber property, so on this cases you can extract the serial number from the <code>PnPDeviceID</code> property.</p> <p>Check this sample code.</p> <pre><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. </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload