2016-08-06 14 views
0

Ich entwickle ein Programm, das eine Hardware verwendet (ich verwende Arduino), um Daten zu sammeln und dann die Daten in der Datenbank zu speichern. Da ich nicht sicher sein kann, dass der Serialport die Daten empfängt, versuche ich ein Code-Snippet zu implementieren, um die Hardware-Entfernung zu deklarieren und dann zu überprüfen, ob mein gewünschtes Gerät noch angeschlossen ist oder den Benutzer anderweitig informiert. Was ich gekommen, um nun ist:Wissen, ob ein bestimmtes Gerät entfernt wurde C#

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

, die mich informiert, ob Änderungen in Geräteverbindung mit dem PC passiert ist. Auch der folgende Code sagt mir über die Existenz des Arduino in der Liste der angeschlossenen Geräte:

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

Wie auch immer, wenn ich die Codes mische mich zu informieren, wenn Arduino der Steckdose gezogen wird, sie entspricht nicht miteinander und throw der Fehler von:

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. 

Jede Hilfe wird geschätzt, Vielen Dank im Voraus.

PS: Für Ihre weitere Informationen, die ganze codiert ist:

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

Nicht wirklich genug Informationen, um meine beste Vermutung ist, dass Sie einige threading Regeln verletzen. Schwer zu sagen, ohne Ihren Init-Code zu sehen, wie Sie den WndProc registrieren, etc. Sie könnten auch eine innere Ausnahme haben, die ausführlicher erklärt, was vor sich geht. –

Antwort

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