2012-05-11 2 views
5

내 C# 응용 프로그램은 COM 포트를 사용합니다. 나는 대부분의 프로그램에 공통적으로 필요한 약간의 어려움을 겪고있다. Portnames의 목록이 변경되면 이벤트를 가져와야합니다. 사용자가 사용할 수있는 포트 이름 목록에서 선택할 수있는 선택 상자가 있습니다. 누구든지이 코드 스 니펫을 가지고 있습니까? 고맙습니다.새 COM 포트 사용 가능 이벤트

+1

일반적인 '새로운 USB 장치'또는 '새로운 PNP 장치'시스템 이벤트를 볼 수 있지만 새 COM 포트가 나타나기 전에 장치 초기화가 완료 될 때까지 잠시 기다려야 할 수도 있습니다. – Rup

+1

@Rup - 정확합니다. 장치 알림과 System.IO.Ports.SerialPort.GetPortNames() 사이에 변경 사항이 반영 될 때까지 지연이 있습니다. 따라서 목록이 업데이트 될 때 알림을받는 것이 좋을 것입니다. – GTAE86

답변

2

COM 포트가 변경되는 경우는 흔하지 않지만 일반적인 경우는 아닙니다.

가장 쉬운 방법은 타이머를 사용하고 10-30 초마다 COM 포트 목록을 열거하고 변경된 경우 목록을 업데이트합니다. :. 사용자의 USB 시리얼 어댑터를 연결 한 경우 간단한 양식 응용 프로그램을 만듭니다

+2

http://www.codeproject.com/Articles/60579/A-USB-Library-to-Detect-USB-Devices는 USB 연결/분리 이벤트를 수신하는 방법을 보여줍니다. 또한 사용자가 10-30 초가 지나치게 길어서 새로 고침 버튼을 +1 할 수 없습니다. – Simon

2

을 목록은 기본적으로 만 변경됩니다 양식에 다음 코드를 넣어 -

더 나은 여전히는 "재생 목록"버튼을 제공

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

Windows 서비스 메시지 펌프에서이 작업을 수행 할 수 있습니까? OS : Win7. 그렇지 않다면 해결 방법은 무엇입니까? –

+0

@AdrianSalazar : 모르겠다. 한번도 시도하지 않았다. 그러나 나는 그것이 작동하지 않아야하는 어떤 이유도 보지 못합니다. 간단히 시도해보십시오. 문제가 해결되지 않으면 새로운 질문을하십시오. – Oliver

+0

작은 "무시 키워드"는 내가 걱정하고있는 키워드입니다. Windows 서비스 내부에서이 특정 메서드를 본 적이 없으므로 무시할 수 있습니다. –

4
또한 "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

매우 깔끔한 솔루션! 고마워! – Ian

+0

ComPorts를 반복하는 동안 ComPorts가 업데이트되면이 코드가 예외를 throw합니다. – GTAE86