如何知道特定设备是否删除了C#

时间:2016-08-06 15:47:35

标签: c# serial-port wndproc

我正在开发一个程序,它使用硬件(我正在使用Arduino)来收集数据,然后将数据存储在数据库中。由于无法确保serialport正在接收数据,我正在尝试实现一些代码片段以声明硬件删除,然后检查是否仍然连接了我所需的设备或以其他方式通知用户。 我现在要做的是:

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;
        }
    }

通知我是否发生了与PC的设备连接的任何更改。以下代码告诉我在连接设备列表中是否存在arduino:

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 */
        }

然而,当我混合代码通知我何时拔掉arduino,他们不相互遵守并抛出错误:

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.

感谢任何帮助,提前致谢。

PS:有关您的进一步信息,整个编码是:

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;
        }
    }

1 个答案:

答案 0 :(得分:0)

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();
    }
}