I found several fragments and .pas files that can detect when USB drives are installed and removed. Some give all sorts of good information, but I need a unique device serial number, not a volume serial number.
My current .pas file (which I donโt remember where I found) also seems to be detecting SD cards (which I like). If you want to look, you can find it here (it returns the disk number and is inserted / deleted):
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.
PS Code selection is not performed.
Generally; When the removable is inserted / removed, get the drive letter and unique serial number. Perhaps combine the given code with the WMI call "where Index = found_index".
**** EDIT! **** I deleted the "where" clause in the code provided by RRUZ. I finally figured out how to handle arrays, so I use this to find Capabilities [i] = 7 to get all removable media. Now I just need to connect this code with the above code. I think using an index, but I don't know how to use GetDrive MapInfo. If you could give me an example of getting a drive letter, my question will be resolved.