如何获得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; 

但它不会返回正确的结果!

Solutions Collecting From Web of "如何获得USB闪存驱动器的制造商序列号?"

opc0de, 根据你的意见,我会给你一个使用WMI的示例。

首先,当您格式化磁盘时,您发布的代码(使用GetVolumeInformation函数)将返回由Windows分配的序列号。

好消息是存在两个wmi类将暴露一个称为SerialNumber的属性,它存储the Number allocated by the manufacturer to identify the physical media. 这些类是Win32_DiskDriveWin32_PhysicalMedia

现在坏消息,不幸的是,这个类不直接与逻辑磁盘的字母(C,D,E,F …)相关联,因为您必须调用另一个wmi类来查找逻辑驱动程序字母和物理驱动器。

所以你必须先找到这个链接才能获得序列号。 找到这种关联的顺序就是这样。

Win32_DiskPartition – > Win32_LogicalDiskToPartition – > Win32_DiskDrive

这是使用Win32_DiskDrive类获取USB序列号的代码。

 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的应用程序,它可以帮助您生成使用WMI访问系统信息的delphi代码。

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. 

您可以尝试GLib中的组件TDiskInfo来获取SerialNumber。
它不使用WMI,但在某些系统(磁盘类型)不检索数字。
尝试一下。 免费。

问候。