How to find the unique serial number of a flash device?

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.

+4
source share
1 answer

You can use the WMI library with Magenta Systems , which hurts the most about using WMI queries. The free download includes source code and a sample project that allows you to play with the API and queries in your heart-friendly content. You will want to keep a link to the official Microsoft documentation, which will help you to execute what query to get what information ... your interested in querying classes using SQL, for example, syntax queries.

For example, query execution

 SELECT * FROM Win32_DiskDrive Where InterfaceType = 'USB' 

returns a large amount of information about all USB devices that are currently connected to the device. Then you can use PNPDeviceID as a unique identifier.

EDIT checking the only USB device that was convenient for me returned the hardware serial number โ€œuโ€, but a very long and valid kind of PNPDeviceID, which seemed to include the serial number, so I suggested that the field.

EDIT . You can get the drive letter by running a query with Win32_LogicalDisk , you can also query Win32_DiskDriveToDiskPartition , which contains the mapping between Win32_DiskDrive and Win32_DiskPartition . Finally, Win32_LogicalDiskToPartition then maps the logical drive to a partition, which in turn allows you to associate a physical USB drive with a specific drive letter.

+4
source

All Articles