以前の質問で「フラッシュデバイスの一意のシリアル番号を見つける方法は?」ドライブ文字を取得する方法を尋ねることになりました。その問題は解決されました。
しかし、私の最初の質問には答えられていません。リムーバブルデバイス(USBドライブ、SDカード、(外付けHDD?)など)を区別し、再接続したときに常に認識できるようにしたかったのです。これは他のコンピュータでも可能です。幸い、ドライブがフォーマットされているかどうかは気にしないので(プログラムで新しいドライブとして扱われる場合)、認識の一部としてパーティションIDとボリュームIDを使用できますか?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.
編集
ドライブが挿入されたときにドライブを検出するコードはすでに機能していることを追加する必要がありますが、ドライブ文字しか表示されません。そのドライブ文字を使用して、WMIから他のすべての情報を取得します。
最終編集
私は、開発者が認識のためにパーティション/ボリュームIDを安全に使用できることを読みました。頼りにできますか?
解決策:
つまり、「一意の」IDを読み取ることは実行可能な解決策ではないため、これを回避するには2つの方法があります。
- プログラムが認識できる一意のIDを使用して隠しファイルをドライブに保存します(ローカルデータベースと比較してください)。
- ドライブに関連するすべてのものを非表示の設定ファイルの形式でドライブに保存します。プログラム自体には設定がないので、このアプローチを採用しました。すべての設定はパーティションごとです。これにより、設定/プログラムも移植可能になります。