2012-05-11 6 views
5

私のC#アプリケーションはCOMポートを使用します。私はほとんどのプログラムに共通するべきいくつかの困難を抱えています。ポートネームのリストが変わったときにイベントを取得する必要があります。ユーザーが使用可能なポート名の一覧から選択できる選択ボックスがあります。誰にもこれのためのコードスニペットがありますか?ありがとうございました。新しい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が更新されると、このコードは例外をスローします。 – GTAE86

関連する問題