gpt4 book ai didi

delphi - 始终检测可移动设备的最佳方法

转载 作者:行者123 更新时间:2023-12-03 15:01:44 25 4
gpt4 key购买 nike

在我之前的问题“如何查找闪存设备的唯一序列号?”中我最终询问了一种获取驱动器号的方法。这个问题已经解决了。

但是,我最初的问题尚未得到解答。我希望能够区分可移动设备(USB 驱动器、SD 卡、(外部 HDD?)等),并且在重新连接时始终能够再次识别它们。这在任何其他计算机上也应该是可能的。幸运的是,我不关心驱动器被格式化(如果/当它们被格式化时,它们在我的程序中被视为新驱动器),所以我可以使用分区和卷 ID 作为我的识别的一部分吗?我问这个问题是因为 PNPDeviceID 不是唯一的。我发现这取决于读取它的硬件,见下图:

alt text

alt text

因此,我正在寻找一种使用以下命令检测和识别任何计算机上的任何可移动设备的方法: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 不是一个可行的解决方案,因此有两种方法可以解决此问题:

  1. 使用程序可以识别的唯一 ID 将隐藏文件保存在驱动器上(与本地数据库相比)。
  2. 以隐藏设置文件的形式将与驱动器相关的所有内容保存在驱动器上。我采用这种方法是因为程序本身没有任何设置。所有设置均针对每个分区。这也使得设置/程序可移植。

最佳答案

您应该能够使用卷 ID 与磁盘总大小和卷名称配对来确定磁盘是否相同,尽管卷 ID 本身就足够了。

唯一的问题可能是批量生产的媒体。在某些情况下,所有副本的卷 ID、磁盘大小和卷名称都匹配。

编辑 我不确定您是否绝对可以在所有设备上绕过它。每个供应商的硬件都不同,并且规范有待解释,这就是为什么某些设备的序列号为空,而另一些则不是的原因。您唯一的希望是自己提供硬件或需要以可预测的方式运行的特定硬件。

如果您可以写入设备,并且用户可以接受,您可以创建一个包含唯一标识符(例如 GUID)的只读系统隐藏文件,并使用该文件进行比较。这只会阻止使用默认设置(隐藏系统文件,并且未选中显示隐藏文件)运行 Windows 的普通用户复制文件,并且在检查中还包括卷 ID、磁盘大小和卷名称会坚持认为仅允许镜像设备。它可能无法获取所有实例,但可能已经足够了。

关于delphi - 始终检测可移动设备的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1948780/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com