我找到了几个片段和.pas文件,可以检测何时插入和移除USB闪存驱动器。有些提供了所有类型的好信息,但我需要的是设备的唯一序列号,而不是卷的序列号。
我当前的.pas文件(我不记得我发现的地方)似乎也检测到SD卡(我喜欢)。如果你想要一个外观,你可以在这里找到它(它只返回驱动器号并插入/删除):
unit UsbDetector;
interface
uses Classes;
type
TUsbDriveChanged = procedure (Sender: TObject; Drive: string; Attached: boolean) of object;
procedure StartUsbDetector(NotifyProc: TUsbDriveChanged);
procedure StopUsbDetector;
implementation
uses Windows, Messages, Forms, SysUtils;
type
TUSBDetector = class(TObject)
private
fUsbDriveChanged: TUsbDriveChanged;
protected
procedure DeviceChanged(Msg: UINT; wParam, lParam: Longint);
procedure DoUsbDriveChanged(Drive: string; Attached: Boolean); dynamic;
public
constructor Create(NotifyProc: TUsbDriveChanged);
destructor Destroy; override;
property OnUsbDriveChanged: TUsbDriveChanged read fUsbDriveChanged;
end;
var mUSBDetector: TUSBDetector;
procedure StartUsbDetector(NotifyProc: TUsbDriveChanged);
begin
if not Assigned(mUsbDetector) then
mUsbDetector := TUsbDetector.Create(NotifyProc);
end;
procedure StopUsbDetector;
begin
FreeAndNil(mUsbDetector);
end;
{----------------------------------------------------------------------------}
// Device constants
const
DBT_DEVICEARRIVAL = $00008000;
DBT_DEVICEREMOVECOMPLETE = $00008004;
DBT_DEVTYP_VOLUME = $00000002;
// Device structs
type
_DEV_BROADCAST_HDR = packed record
dbch_size: DWORD;
dbch_devicetype: DWORD;
dbch_reserved: DWORD;
end;
DEV_BROADCAST_HDR = _DEV_BROADCAST_HDR;
TDevBroadcastHeader = DEV_BROADCAST_HDR;
PDevBroadcastHeader = ^TDevBroadcastHeader;
type
_DEV_BROADCAST_VOLUME = packed record
dbch_size: DWORD;
dbch_devicetype: DWORD;
dbch_reserved: DWORD;
dbcv_unitmask: DWORD;
dbcv_flags: WORD;
end;
DEV_BROADCAST_VOLUME = _DEV_BROADCAST_VOLUME;
TDevBroadcastVolume = DEV_BROADCAST_VOLUME;
PDevBroadcastVolume = ^TDevBroadcastVolume;
var
fPrevWndProc: TFNWndProc = nil;
function UsbWndProc(hWnd: HWND; Msg: UINT; wParam, lParam: Longint): Longint; stdcall;
begin
Result := CallWindowProc(fPrevWndProc, hWnd, Msg, wParam, lParam);
if (Msg = WM_DEVICECHANGE) and (mUsbDetector <> nil) then
mUsbDetector.DeviceChanged(Msg, wParam, lParam);
end;
constructor TUSBDetector.Create(NotifyProc: TUsbDriveChanged);
begin
inherited Create;
fUsbDriveChanged := NotifyProc;
if not Assigned(fPrevWndProc) then
begin
fPrevWndProc := TFNWndProc(GetWindowLong(Application.Handle, GWL_WNDPROC));
SetWindowLong(Application.Handle, GWL_WNDPROC, LongInt(@UsbWndProc));
end;
end;
destructor TUSBDetector.Destroy;
begin
//SetWindowLong(Application.Handle, GWL_WNDPROC, LongInt(@fPrevWndProc));
inherited Destroy;
end;
procedure TUSBDetector.DeviceChanged(Msg: UINT; wParam, lParam: LongInt);
var
lpdbhHeader: PDevBroadcastHeader;
lpdbvData: PDevBroadcastVolume;
dwIndex: Integer;
lpszDrive: string;
begin
// Get the device notification header
lpdbhHeader := PDevBroadcastHeader(lParam);
// Handle the message
lpszDrive := '';
case WParam of
DBT_DEVICEARRIVAL: {a USB drive was connected}
begin
if lpdbhHeader^.dbch_devicetype = DBT_DEVTYP_VOLUME then
begin
lpdbvData := PDevBroadcastVolume(lParam);
for dwIndex := 0 to 25 do
begin
if (lpdbvData^.dbcv_unitmask shr dwIndex) = 1 then
begin
lpszDrive := lpszDrive + Chr(65 + dwIndex) + ':\';
break;
end;
end;
DoUsbDriveChanged(lpszDrive, True);
end;
end;
DBT_DEVICEREMOVECOMPLETE: {a USB drive was removed}
begin
if lpdbhHeader^.dbch_devicetype = DBT_DEVTYP_VOLUME then
begin
lpdbvData := PDevBroadcastVolume(lParam);
for dwIndex := 0 to 25 do
begin
if (lpdbvData^.dbcv_unitmask shr dwIndex) = 1 then
begin
lpszDrive := lpszDrive + Chr(65 + dwIndex) + ':\';
break;
end;
end;
DoUsbDriveChanged(lpszDrive, False);
end;
end;
end;
end;
procedure TUSBDetector.DoUsbDriveChanged(Drive: string; Attached: Boolean);
begin
if Assigned(fUsbDriveChanged) then
fUsbDriveChanged(Self, Drive, Attached);
end;
end.
P.S。代码突出显示失败。
总而言之; 插入/移除可移动设备时,请获取驱动器号及其唯一的序列号。也许将已经给定的代码与WMI调用“where index = found_index”结合起来。
**** EDIT!**** 我删除了RRUZ给出的代码中的“where”子句。我终于找到了如何处理数组,所以我用它来找到Capabilities [i] = 7来获取所有可移动媒体。现在我只需要将此代码与上面的代码连接起来。我在想使用Index,但我不知道如何使用GetDrive MapInfo。如果你能给我一个关于获得驱动器号的例子,我的问题就解决了。
答案 0 :(得分:4)
您可以使用Magenta Systems的WMI库,它可以解决使用WMI查询的大部分问题。免费下载包括源代码和示例项目,允许您使用API并查询您的内容。您需要保留一个指向官方Microsoft API documentation的链接,它将帮助您执行哪些查询以获取哪些信息...您有兴趣使用SQL语法查询来查询类。
例如,执行查询
SELECT * FROM Win32_DiskDrive Where InterfaceType = 'USB'
返回有关当前连接到本机的所有USB设备的大量信息。然后,您可以使用PNPDeviceID作为唯一标识符。
编辑检查我用过的唯一的USB设备返回了硬件序列号“u”,但是看起来很长且有效的PNPDeviceID似乎包含序列号,这就是为什么我建议的那个字段。
编辑您可以通过对Win32_LogicalDisk
执行查询来获取驱动器号,还可以查询Win32_DiskDriveToDiskPartition
,其中包含Win32_DiskDrive
和{{1}之间的映射}}。最后Win32_DiskPartition
然后将逻辑磁盘映射到分区,从而使您能够将物理USB驱动器链接到特定的驱动器号。