Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to detect addition of new serial port?
    text
    copied!<p>To communicate with micro controllers I use the serial port. I use TCommPortDriver 2.1 which works fine. However, it lacks the ability to detect the addition or removal of new comports. This happens regularly during a session.</p> <p>Is there an event that tells when a comport has been added or removed?</p> <p><strong>Update 1</strong></p> <p>I tried the first suggestion of RRUZ and turned it into a standalone program. It reacts on a <code>WM_DEVICECHANGE</code> when the cable is plugged in or out, but <code>WParam</code> does not show arrival or removal of the device. Results are:</p> <pre><code>msg = 537, wparam = 7, lparam = 0 msg = 537, wparam = 7, lparam = 0 msg = 537, wparam = 7, lparam = 0 </code></pre> <p>The first message is sent when the USB cable is plugged out and the next two when it is plugged in. The message part shows the <code>WM_DEVICECHANGE</code> message (537) but <code>WParam</code> is 7, which is not <code>WM_DEVICECHANGE</code> or <code>DBT_DEVICEARRIVAL</code>. I modified the code somewhat in order the message to be processed but as <code>LParam</code> is zero this is no use. Results are identical to VCL and FMX. As a check see code below.</p> <p><strong>Update 2</strong></p> <p>I now got the WMI code running. It only fires when a COM port is added, no reaction when one is removed. Results:</p> <pre><code>TargetInstance.ClassGuid : {4d36e978-e325-11ce-bfc1-08002be10318} TargetInstance.Description : Arduino Mega ADK R3 TargetInstance.Name : Arduino Mega ADK R3 (COM4) TargetInstance.PNPDeviceID : USB\VID_2341&amp;PID_0044\64935343733351E0E1D1 TargetInstance.Status : OK </code></pre> <p>Might this explain the fact that in the other code this is not seen as the addition of a COM port? It appears to see the new connection as a USB port (what it actually is). The Arduino driver translates this into a COM port but that is not recognized by WMI. Windows messaging 'sees' a COM port change but cannot detect whether it is added or removed.</p> <p>Anyhow: the device change works. I only need to enumerate the COM ports to see which one are actually present and that was something I already did manually. Now I can do that automatically with <code>WM_DEVICECHANGE</code>. I just add an event to the CPDrv component.</p> <p>Thanks RRUZ for your code and help!</p> <pre><code> unit dev_change; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; type TProc = procedure (text: string) of object; BroadcastHdr = ^DEV_BROADCAST_HDR; DEV_BROADCAST_HDR = packed record dbch_size: DWORD; dbch_devicetype: DWORD; dbch_reserved: DWORD; end; TDevBroadcastHdr = DEV_BROADCAST_HDR; type PDevBroadcastDeviceInterface = ^DEV_BROADCAST_DEVICEINTERFACE; DEV_BROADCAST_DEVICEINTERFACE = record dbcc_size: DWORD; dbcc_devicetype: DWORD; dbcc_reserved: DWORD; dbcc_classguid: TGUID; dbcc_name: Char; end; TDevBroadcastDeviceInterface = DEV_BROADCAST_DEVICEINTERFACE; const DBT_DEVICESOMETHING = $0007; DBT_DEVICEARRIVAL = $8000; DBT_DEVICEREMOVECOMPLETE = $8004; DBT_DEVTYP_DEVICEINTERFACE = $00000005; type TDeviceNotifyProc = procedure(Sender: TObject; const DeviceName: String) of Object; TDeviceNotifier = class private hRecipient: HWND; FNotificationHandle: Pointer; FDeviceArrival: TDeviceNotifyProc; FDeviceRemoval: TDeviceNotifyProc; FOnWin: TProc; procedure WndProc(var Msg: TMessage); public constructor Create(GUID_DEVINTERFACE : TGUID); property OnDeviceArrival: TDeviceNotifyProc read FDeviceArrival write FDeviceArrival; property OnDeviceRemoval: TDeviceNotifyProc read FDeviceRemoval write FDeviceRemoval; destructor Destroy; override; property OnWin: TProc read FOnWin write FOnWin; end; TForm1 = class(TForm) Memo: TMemo; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } DeviceNotifier : TDeviceNotifier; public { Public declarations } procedure arrival(Sender: TObject; const DeviceName: String); procedure report (text: string); end; var Form1: TForm1; implementation {$R *.dfm} constructor TDeviceNotifier.Create(GUID_DEVINTERFACE : TGUID); var NotificationFilter: TDevBroadcastDeviceInterface; begin inherited Create; hRecipient := AllocateHWnd(WndProc); ZeroMemory (@NotificationFilter, SizeOf(NotificationFilter)); NotificationFilter.dbcc_size := SizeOf(NotificationFilter); NotificationFilter.dbcc_devicetype := DBT_DEVTYP_DEVICEINTERFACE; NotificationFilter.dbcc_classguid := GUID_DEVINTERFACE; //register the device class to monitor FNotificationHandle := RegisterDeviceNotification(hRecipient, @NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE); end; procedure TDeviceNotifier.WndProc(var Msg: TMessage); var Dbi: PDevBroadcastDeviceInterface; begin OnWin (Format ('msg = %d, wparam = %d, lparam = %d', [msg.Msg, msg.WParam, msg.LParam])); with Msg do if (Msg = WM_DEVICECHANGE) and ((WParam = DBT_DEVICEARRIVAL) or (WParam = DBT_DEVICEREMOVECOMPLETE) or (WParam = DBT_DEVICESOMETHING)) then try Dbi := PDevBroadcastDeviceInterface (LParam); if Dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE then begin if WParam = DBT_DEVICEARRIVAL then begin if Assigned(FDeviceArrival) then FDeviceArrival(Self, PChar(@Dbi.dbcc_name)); end else if WParam = DBT_DEVICEREMOVECOMPLETE then begin if Assigned(FDeviceRemoval) then FDeviceRemoval(Self, PChar(@Dbi.dbcc_name)); end; end; except Result := DefWindowProc(hRecipient, Msg, WParam, LParam); end else Result := DefWindowProc(hRecipient, Msg, WParam, LParam); end; destructor TDeviceNotifier.Destroy; begin UnregisterDeviceNotification(FNotificationHandle); DeallocateHWnd(hRecipient); inherited; end; procedure TForm1.arrival(Sender: TObject; const DeviceName: String); begin report (DeviceName); ShowMessage(DeviceName); end; procedure TForm1.FormCreate(Sender: TObject); const GUID_DEVINTERFACE_COMPORT : TGUID = '{86E0D1E0-8089-11D0-9CE4-08003E301F73}'; begin DeviceNotifier:=TDeviceNotifier.Create(GUID_DEVINTERFACE_COMPORT); DeviceNotifier.FDeviceArrival:=arrival; DeviceNotifier.OnWin := report; end; procedure TForm1.FormDestroy(Sender: TObject); begin DeviceNotifier.Free; end; procedure TForm1.report (text: string); begin Memo.Lines.Add (text); end; end. </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload