В моем предыдущем вопросе «Как найти уникальный серийный номер флеш-устройства?» Я закончил тем, что спросил способ получить букву диска. Эта проблема решена.
Тем не менее, мой первоначальный вопрос не получил ответа. Я хотел, чтобы можно было различать съемные устройства (USB-накопители, SD-карты, (внешние жесткие диски?) И т. Д.) И всегда иметь возможность снова их распознавать при повторном подключении. Это также должно быть возможно на любом другом компьютере. К счастью, меня не волнует форматирование дисков (если / когда они в моей программе считаются новыми дисками), поэтому я могу использовать идентификаторы разделов и томов как часть моего распознавания? Я спрашиваю это, поскольку PNPDeviceID является НЕ уникальным. Я обнаружил, что это зависит от аппаратного обеспечения его чтения, см. Ниже изображения:
Итак, я ищу способ обнаружения и распознавания любого съемного устройства на любом компьютере с помощью следующего: Win32_DiskDrive , Win32_DiskPartition , Win32_LogicalDisk, Я благодарю RRUZ за оригинальный код:
program GetWMI_USBConnectedInfo;
{$APPTYPE CONSOLE}
uses
Windows,
Classes,
ActiveX,
Variants,
SysUtils,
WbemScripting_TLB in '..\..\Documents\RAD Studio\5.0\Imports\WbemScripting_TLB.pas';
procedure GetUSBDiskDriveInfo;
var
WMIServices : ISWbemServices;
Root,a,b : ISWbemObjectSet;
Item,Item2 : Variant;
i,ii,iii,iiii: Integer;
start,stop,freq:Int64;
begin
QueryPerformanceFrequency(freq);
QueryPerformanceCounter(start);
WMIServices := CoSWbemLocator.Create.ConnectServer('.', 'root\cimv2','', '', '', '', 0, nil);
Root := WMIServices.ExecQuery('Select * From Win32_DiskDrive','WQL', 0, nil);
for i := 0 to Root.Count - 1 do
begin
Item := Root.ItemIndex(i);
for ii := VarArrayLowBound(Item.Capabilities, 1) to VarArrayHighBound(Item.Capabilities, 1) do if (Item.Capabilities[ii] = 7) then begin
Writeln('Caption '+VarToStr(Item.Caption));
Writeln('Name '+VarToStr(Item.Name));
Writeln('DeviceID '+VarToStr(Item.DeviceID));
Writeln('Partitions '+VarToStr(Item.Partitions));
Writeln('PNPDeviceID '+VarToStr(Item.PNPDeviceID));
Writeln('SerialNumber '+VarToStr(Item.SerialNumber));
Writeln('Signature '+VarToStr(Item.Signature));
a := WMIServices.ExecQuery('ASSOCIATORS OF {Win32_DiskDrive.DeviceID=''' + VarToStr(Item.DeviceID) + '''} WHERE AssocClass = Win32_DiskDriveToDiskPartition','WQL', 0, nil);
for iiii := 0 to a.Count - 1 do begin
b := WMIServices.ExecQuery('ASSOCIATORS OF {Win32_DiskPartition.DeviceID=''' + VarToStr(Variant(a.ItemIndex(iiii)).DeviceID) + '''} WHERE AssocClass = Win32_LogicalDiskToPartition','WQL', 0, nil);
for iii := 0 to b.Count - 1 do begin
Item2 := b.ItemIndex(iii);
Writeln('Drive = ' + Item2.Caption);
end;
end;
Writeln;
Writeln;
end;
end;
QueryPerformanceCounter(stop);
if (freq > 0) then
Writeln('Time took: ' + FloatToStr((stop-start) / freq))
else
Writeln('Unable to measure time!');
end;
begin
try
CoInitialize(nil);
GetUSBDiskDriveInfo;
Readln;
CoUninitialize;
except
on E:Exception do
Begin
CoUninitialize;
Writeln(E.Classname, ': ', E.Message);
Readln;
End;
end;
end.
EDIT
Я должен добавить, что код, определяющий диски, когда они вставлены, уже работает, хотя он только дает мне букву диска. Я использую эту букву, чтобы получить всю остальную информацию от WMI.
Окончательное редактирование
Я прочитал, что разработчики могут безопасно использовать ID раздела / тома для распознавания. Могу ли я рассчитывать на это?
Решение:
Итак, поскольку чтение «уникальных» идентификаторов не является жизнеспособным решением, есть два способа обойти это:
- Сохраните скрытый файл на диске с уникальным идентификатором, который может распознать программа (сравните с локальной базой данных).
- Сохраните все, что связано с диском , на диске в виде скрытого файла настроек. Я выбрал этот подход, так как сама программа не имеет никаких настроек. Все настройки на раздел. Это также делает настройки / программы переносимыми.