如何获得USB闪存驱动器的制造商序列号? [英] How to get manufacturer serial number of an USB flash drive?
问题描述
我已经尝试过:
函数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);
结果:= VolumeSerialNumber;
结束
但它没有返回正确的结果!
opc0de,根据您的意见,我将给您一个使用WMI的示例。
首先,您发布的代码(使用 GetVolumeInformation
功能)返回格式化磁盘时Windows分配的序列号。
好消息是存在两个wmi类,它们公开了一个名为 SerialNumber
的属性,存储制造商分配的号码来标识物理媒体。
这些类是 Win32_DiskDrive
和 Win32_PhysicalMedia
。
不幸的是,这个类不直接与字母相关联(C, D,E,F ...),因为您必须调用另一个wmi类来找到逻辑驱动程序字母和物理驱动器之间的链接。
所以您必须先找到此链接才能获得序列号。找到这个关联的顺序是这样的。
Win32_DiskPartition
- > Win32_LogicalDiskToPartition
- > Win32_DiskDrive
这是获取的代码使用 Win32_DiskDrive $的usb的序列号c $ c>
类。
程序GetWMI_Info;
{$ APPTYPE CONSOLE}
使用
SysUtils,
StrUtils,
ActiveX,
ComObj,
变种
函数VarArrayToStr(const vArray:variant):string;
函数_VarToStr(const V:variant):string;
var
Vt:integer;
begin
Vt:= VarType(V);
case Vt
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:结果:= VarArrayToStr(Variant(V));
结束
结束
var
i:integer;
begin
结果:='[';
if(VarType(vArray)和VarArray)= 0然后
结果:= _VarToStr(vArray)
else
for i:= VarArrayLowBound(vArray,1)到VarArrayHighBound(vArray ,1)do
if i = VarArrayLowBound(vArray,1)then
Result:= Result + _VarToStr(vArray [i])
else
结果:= Result +'|' + _VarToStr(vArray [i]);
结果:= Result +']';
结束
函数VarStrNull(const V:OleVariant):string; //避免使用空字符串的问题
begin
结果:='';
如果不是VarIsNull(V)然后
begin
如果VarIsArray(V)then
结果:= VarArrayToStr(V)
else
结果:= VarToStr (V);
结束
结束
函数GetWMIObject(const objectName:String):IDispatch; //创建Wmi实例
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));
结束
函数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;
开始;
结果:='';
objWMIService:= GetWMIObject('winmgmts:\\localhost\root\CIMV2'); //连接到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]); //在DeviceID值中删除`\`个字符,因为'\'是WMI中的保留字符。
colPartitions:= objWMIService.ExecQuery(Format('ASSOCIATORS OF {Win32_DiskDrive.DeviceID =%s} WHERE AssocClass = Win32_DiskDriveToDiskPartition',[DeviceID])); //将Win32_DiskDrive类与Win32_DiskDriveToDiskPartition类$ b链接$ b 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'); //将Win32_DiskPartition类与Win32_LogicalDiskToPartition类链接。
oEnumLogical:= IUnknown(colLogicalDisks.NewEnum)as IEnumVariant;
while oEnumLogical.Next(1,objLogicalDisk,iValue)= 0 do
如果VarStrNull(objLogicalDisk.DeviceID)=(Drive +':')然后//比较设备ID
begin
结果:= VarStrNull(objDiskDrive.SerialNumber);
退出;
结束
结束
结束
结束
begin
try
CoInitialize(nil);
try
Writeln(GetUsbDriveSerial('F'));
Readln;
finally
CoUninitialize;
结束
除了
在E上:异常do
begin
Writeln(E.Classname,':',E.Message);
Readln;
结束
结束
结束。
> 更新
USB磁盘的某些驱动程序不会在制造商序列号Win32_DiskDrive.SerialNumber属性,所以在这种情况下,您可以从 PnPDeviceID
属性中提取序列号。
检查此示例代码
{$ APPTYPE CONSOLE}
使用
SysUtils,
StrUtils,
ActiveX,
ComObj,
变体;
函数VarStrNull(const V:OleVariant):string; //避免空变量的问题
begin
结果:='';
如果不是VarIsNull(V)then
结果:= VarToStr(V);
结束
函数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;
开始;
结果:='';
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]); //在DeviceID值中删除`\`个字符,因为'\'是WMI中的保留字符。
colPartitions:= objWMIService.ExecQuery(Format('ASSOCIATORS OF {Win32_DiskDrive.DeviceID =%s} WHERE AssocClass = Win32_DiskDriveToDiskPartition',[DeviceID])); //将Win32_DiskDrive类与Win32_DiskDriveToDiskPartition类$ b链接$ b 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'); //将Win32_DiskPartition类与Win32_LogicalDiskToPartition类链接。
oEnumLogical:= IUnknown(colLogicalDisks.NewEnum)as IEnumVariant;
while oEnumLogical.Next(1,objLogicalDisk,iValue)= 0 do
begin
如果SameText(VarStrNull(objLogicalDisk.DeviceID),Drive +':')则//比较设备ID
begin
结果:= VarStrNull(objDiskDrive.PnPDeviceID);
如果AnsiStartsText('USBSTOR',结果)然后
开始
iValue:= LastDelimiter('\',Result);
结果:=复制(结果,iValue + 1,长度(结果));
结束
objLogicalDisk:=未分配;
退出;
结束
objLogicalDisk:=未分配;
结束
objPartition:=未分配;
结束
objDiskDrive:=未分配;
结束
结束
begin
try
CoInitialize(nil);
try
Writeln(GetUsbDriveSerial('F'));
Readln;
finally
CoUninitialize;
结束
除了
在E上:异常do
begin
Writeln(E.Classname,':',E.Message);
Readln;
结束
结束
结束。
How can I retrieve the manufacturer serial number of an USB flash drive in Delphi ?
I have tried this:
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;
But it doesn't return correct result!
opc0de, according to your comments i will give you a sample using the WMI.
First, the code which you posted (using the GetVolumeInformation
function) return the serial number assigned by windows when you format a disk.
The good news are which exist two wmi classes wich exposes a property called SerialNumber
which store the Number allocated by the manufacturer to identify the physical media.
these classes are Win32_DiskDrive
and Win32_PhysicalMedia
.
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.
so you must find this link previous to obtain the serial number. the sequence to find this association is like this.
Win32_DiskPartition
-> Win32_LogicalDiskToPartition
-> Win32_DiskDrive
this is the code to obtain the serial number of a usb using the Win32_DiskDrive
class.
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.
By the way some time ago i wrote an application called WMI Delphi Code Creator which can help you to generate delphi code to access the system info using the WMI.
UPDATE
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 PnPDeviceID
property.
Check this sample 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.
这篇关于如何获得USB闪存驱动器的制造商序列号?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!