I am developing a program that uses a hardware (I am using Arduino) to collect data and then store the data in the database. As there is no way to get assured that the serialport is receiving the data, I am trying to implement some code snippet to declare hardware removal and then check if there is my desired device still connected or otherwise inform the user. What I have come to up to now is:
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case WM_DEVICECHANGE:
switch ((int)m.WParam)
{
case DBT_DEVICEARRIVAL:
listBox1.Items.Add("New Device Arrived");
int devType = Marshal.ReadInt32(m.LParam, 4);
if (devType == DBT_DEVTYP_PORT)
{
string portName = Marshal.PtrToStringAuto((IntPtr)((long)m.LParam + 12));
listBox1.Items.Add("the name of the port is " + portName);
}
break;
case DBT_DEVICEREMOVECOMPLETE:
{
listBox1.Items.Add("Device Removed");
}
break;
}
break;
}
}
which informs me if any changes in device connection to the PC has happened. Also the following code tells me about existence of the arduino in the list of connected devices:
ManagementScope connectionScope = new ManagementScope();
SelectQuery serialQuery = new SelectQuery("SELECT * FROM Win32_SerialPort");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(connectionScope, serialQuery);
try
{
foreach (ManagementObject item in searcher.Get())
{
string desc = item["Description"].ToString();
string deviceId = item["DeviceID"].ToString();
if (!desc.Contains("Arduino"))
{
// Inform the user about the disconnection of the arduino
}
}
}
catch //(ManagementException e)
{
/* Do Nothing */
}
How ever, when I mix the codes to inform me when arduino is unplugged, they do not comply with each other and throw the error of:
Transition into COM context 0x8ff990 for this RuntimeCallableWrapper failed with the following error: An outgoing call cannot be made since the application is dispatching an input-synchronous call. (Exception from HRESULT: 0x8001010D (RPC_E_CANTCALLOUT_ININPUTSYNCCALL)). This is typically because the COM context 0x8ff990 where this RuntimeCallableWrapper was created has been disconnected or it is busy doing something else and cannot process the context transition. No proxy will be used to service the request on the COM component and calls will be made to the COM component directly. This may cause corruption or data loss. To avoid this problem, please ensure that all COM contexts/apartments/threads stay alive and are available for context transition, until the application is completely done with the RuntimeCallableWrappers that represents COM components that live inside them.
Any Help is appreciated, Thanks in advance.
PS: For your further information, the whole coded is:
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case WM_DEVICECHANGE:
switch ((int)m.WParam)
{
case DBT_DEVICEARRIVAL:
listBox1.Items.Add("New Device Arrived");
int devType = Marshal.ReadInt32(m.LParam, 4);
if (devType == DBT_DEVTYP_PORT)
{
string portName = Marshal.PtrToStringAuto((IntPtr)((long)m.LParam + 12));
listBox1.Items.Add("the name of the port is " + portName);
}
break;
case DBT_DEVICEREMOVECOMPLETE:
{
listBox1.Items.Add("Device Removed");
ManagementScope connectionScope = new ManagementScope();
SelectQuery serialQuery = new SelectQuery("SELECT * FROM Win32_SerialPort");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(connectionScope, serialQuery);
try
{
foreach (ManagementObject item in searcher.Get())
{
string desc = item["Description"].ToString();
string deviceId = item["DeviceID"].ToString();
if (desc.Contains("Arduino"))
{
MessageBox.Show(deviceId);
}
}
}
catch //(ManagementException e)
{
/* Do Nothing */
}
}
break;
}
break;
}
}
public partial class Form1 : Form
{
ManagementEventWatcher watcher;
// Not all arduinos have 'Arduino' in their serialport driver 'Description', So check for a Com port Number.
private static string MustHavePort = "COM3"; //Port to check for.
public Form1()
{
InitializeComponent();
watcher = new ManagementEventWatcher("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2 or EventType = 3");
watcher.EventArrived += new EventArrivedEventHandler(USBChangedEvent);
watcher.Start();
}
public void USBChangedEvent(object sender, EventArrivedEventArgs e)
{
(sender as ManagementEventWatcher).Stop();
this.Invoke((MethodInvoker)delegate
{
ManagementObjectSearcher deviceList = new ManagementObjectSearcher("Select Name, Description, DeviceID from Win32_SerialPort");
// List to store available USB serial devices plugged in. (Arduino(s)/Cell phone(s)).
List<String> ComPortList = new List <String>();
listBox1.Items.Clear();
textBox1.Text = "";
// Any results? There should be!
if (deviceList != null)
{
// Enumerate the devices
foreach (ManagementObject device in deviceList.Get())
{
string SerialPortNumber = device["DeviceID"].ToString();
string serialName = device["Name"].ToString();
string SerialDescription = device["Description"].ToString();
ComPortList.Add(SerialPortNumber);
listBox1.Items.Add(SerialPortNumber);
listBox1.Items.Add(serialName);
listBox1.Items.Add(SerialDescription);
}
}
else
{
listBox1.Items.Add("NO SerialPorts AVAILABLE!");
// Inform the user about the disconnection of the arduino ON PORT 3 etc...
SendAlarm();
}
if (!ComPortList.Contains(MustHavePort))
{
// Inform the user about the disconnection of the arduino ON PORT 3 etc...
SendAlarm();
}
});
(sender as ManagementEventWatcher).Start();
}
private void SendAlarm()
{
textBox1.Text = "Alarm..." + MustHavePort + "Port Missing...";
MessageBox.Show("Error " + MustHavePort + " Port Missing!!!", "Serial Port Error.");
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
watcher.Stop();
}
}
User contributions licensed under CC BY-SA 3.0