我找到了几个片段和.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,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,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.
总而言之;
插入/移除可移动设备时,请获取驱动器号及其唯一的序列号.也许将已经给定的代码与WMI调用“where index = found_index”结合起来.
****编辑!****
我删除了RRUZ给出的代码中的“where”子句.我终于找到了如何处理数组,所以我用它来找到Capabilities [i] = 7来获取所有可移动媒体.现在我只需要将此代码与上面的代码连接起来.我在想使用Index,但我不知道如何使用GetDrive MapInfo.如果你能给我一个关于获得驱动器号的例子,我的问题就解决了.
解决方法
您可以在
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和Win32_DiskPartition之间的映射.最后,Win32_LogicalDiskToPartition然后将逻辑磁盘映射到分区,从而使您能够将物理USB驱动器链接到特定的驱动器号.