2012-05-11 18 views
5

Moja aplikacja C# używa portów COM. Mam pewne trudności, które powinny być wspólne dla większości programów. Muszę uzyskać zdarzenie, gdy zmieni się lista nazw portowych. Mam pole wyboru, w którym użytkownik może wybrać listę dostępnych nazw portów. Czy ktoś ma fragment kodu do tego? Dziękuję Ci.Nowy dostępny port COM

+1

Przypuszczam, że istnieje ogólne zdarzenie systemowe "nowe urządzenie USB" lub "nowe urządzenie PNP", które można było oglądać, ale może trzeba poczekać sekundę, aż urządzenie zakończy inicjowanie przed pojawieniem się nowych portów COM. – Rup

+1

@Rup - Masz rację. Występuje opóźnienie między powiadomieniem urządzenia i kiedy System.IO.Ports.SerialPort.GetPortNames() odzwierciedli zmianę. Dlatego dobrze byłoby być powiadamianym, gdy lista zostanie zaktualizowana. – GTAE86

Odpowiedz

2

Zmiana portów COM jest zjawiskiem rzadkim, a nie powszechnym.

Najprostszym sposobem jest posiadanie timera i co 10-30 sekund wylicza listę portów COM, a po zmianie, aktualizuje listę.

Jeszcze lepiej, zapewniają przycisk „Odśwież” - lista będzie w zasadzie tylko zmienić, jeśli użytkownik podłączony do USB Serial Adapter w

+2

http://www.codeproject.com/Articles/60579/A-USB-Library-to-Detect-USB-Devital pokaże Ci, jak słuchać zdarzeń podłączania/odłączania USB. Również 10-30 sekund to prawdopodobnie zbyt długo dla użytkownika, +1 głos dla przycisku odświeżania. – Simon

2

Tworzenie prostych aplikacji Form i umieścić następujący kod w postaci:.

protected override void WndProc(ref Message m) 
{ 
    switch (m.Msg) 
    { 
     case 537: //WM_DEVICECHANGE 
      var ports = SerialPort.GetPortNames().OrderBy(name => name); 

      foreach (var portName in ports) 
      { 
       Debug.Print(portName); 
      } 
      break; 
    } 
    base.WndProc(ref m); 
} 
+0

Czy to działa wewnątrz pompy komunikatów usługi systemu Windows? System operacyjny: Win7. Jeśli nie, to w jaki sposób obejść ten problem? –

+0

@AdrianSalazar: Nie wiem, nigdy nie próbowałem. Ale nie widzę żadnego powodu, dla którego nie powinien działać. Po prostu wypróbuj go, a jeśli to nie zadziała, poproś o nowe pytanie dotyczące problemu. – Oliver

+0

Małe słowo "przesłonięcie" jest tym, o co się martwię. Nigdy nie widziałem tej konkretnej metody w usłudze Windows, więc zwracając uwagę, aby ją zastąpić. –

4

To może być również wykonane z pomocą "ManagementEventWatcher":

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.ComponentModel.Composition; 
using System.Linq; 
using System.Text; 
using System.Management; 
using System.IO.Ports; 
using System.Threading; 
using System.Threading.Tasks; 

namespace HmxFlashLoader 
{ 
/// <summary> 
/// Make sure you create this watcher in the UI thread if you are using the com port list in the UI 
/// </summary> 
[Export] 
[PartCreationPolicy(CreationPolicy.Shared)] 
public sealed class SerialPortWatcher : IDisposable 
{ 
    public SerialPortWatcher() 
    { 
     _taskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); 
     ComPorts = new ObservableCollection<string>(SerialPort.GetPortNames().OrderBy(s => s)); 

     WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent"); 

     _watcher = new ManagementEventWatcher(query);   
     _watcher.EventArrived += (sender, eventArgs) => CheckForNewPorts(eventArgs); 
     _watcher.Start();  
    } 

    private void CheckForNewPorts(EventArrivedEventArgs args) 
    { 
     // do it async so it is performed in the UI thread if this class has been created in the UI thread 
     Task.Factory.StartNew(CheckForNewPortsAsync, CancellationToken.None, TaskCreationOptions.None, _taskScheduler); 
    } 

    private void CheckForNewPortsAsync() 
    { 
     IEnumerable<string> ports = SerialPort.GetPortNames().OrderBy(s => s); 

     foreach (string comPort in ComPorts) 
     { 
      if (!ports.Contains(comPort)) 
      { 
       ComPorts.Remove(comPort); 
      } 
     } 

     foreach (var port in ports) 
     {   
      if (!ComPorts.Contains(port)) 
      { 
       AddPort(port); 
      } 
     } 
    } 

    private void AddPort(string port) 
    { 
     for (int j = 0; j < ComPorts.Count; j++) 
     { 
      if (port.CompareTo(ComPorts[j]) < 0) 
      { 
       ComPorts.Insert(j, port); 
       break; 
      } 
     } 

    } 

    public ObservableCollection<string> ComPorts { get; private set; } 

    #region IDisposable Members 

    public void Dispose() 
    { 
     _watcher.Stop();  
    } 

    #endregion 

    private ManagementEventWatcher _watcher; 
    private TaskScheduler _taskScheduler; 
} 

}

+0

Bardzo miłe rozwiązanie! Dzięki stary! – Ian

+0

Myślę, że ten kod rzuci wyjątek, gdy ComPorts zostanie zaktualizowany podczas iteracji ComPorts .... – GTAE86