2012年7月3日火曜日

[C#]SNMP Trap

今回は.NET でSNMP の Trap を検知する方法のご紹介。

System.Management 空間の WMI を使う。


1.参照設定にまずこれを追加する。
2.機能(WMI SNMP プロバイダ)を有効化する
[コントロールパネル] - [プログラムと機能] - [Windows の機能の有効化または無効化]
・簡易ネットワーク管理プロトコル(SNMP)
3.Windows のサービスを動かす。
[コントロールパネル] - [管理ツール] - [サービス]
・SNMP Service
・SNMP Trap
4.コーディング

using System.Management;
        /// <summary>
        /// イベントウォチャー
        /// </summary>
        private ManagementEventWatcher watcher = null;
        /// <summary>
        /// 監視開始
        /// </summary>
        public void Start()
        {
            ManagementPath path = new ManagementPath("\\\\.\\root\\snmp\\localhost:SNMP_RFC1213_MIB_system");
            ManagementScope scope = new ManagementScope(path);
            this.watcher = new ManagementEventWatcher(scope, new EventQuery("SELECT * FROM SnmpNotification"));
            this.watcher.EventArrived += this.trapRecieveEvent;
            this.watcher.Start();
        }
        /// <summary>
        /// 監視停止
        /// </summary>
        public void Stop()
        {
            this.watcher.EventArrived -= this.trapRecieveEvent;
            this.watcher.Stop();
            this.watcher.Dispose();
            this.watcher = null;
        }
        /// <summary>
        /// トラップ受信イベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void trapRecieveEvent(object sender, EventArrivedEventArgs e)
        {
            //---------------------------------------------------------
            // プロパティ取得
            //---------------------------------------------------------
            string agentAddress = e.NewEvent.Properties["AgentAddress"].Value.ToString();
            string agentTransportAddress = e.NewEvent.Properties["AgentTransportAddress"].Value.ToString();
            string agentTransrportProtocol = e.NewEvent.Properties["AgentTransportProtocol"].Value.ToString();
            string community = e.NewEvent.Properties["Community"].Value.ToString();
            string identification = e.NewEvent.Properties["Identification"].Value.ToString();
            if (e.NewEvent.Properties["VarBindList"] != null)
            {
                ManagementBaseObject[] variableBindingArray = (ManagementBaseObject[])e.NewEvent.Properties["VarBindList"].Value;
                List<VariableBinding> variableBindings = new List<VariableBinding>();
                foreach (var mib in variableBindingArray)
                {
                    try
                    {
                        variableBindings.Add(new VariableBinding()
                        {
                            Oid = (string)mib.Properties["ObjectIdentifier"].Value,
                            Encoding = (string)mib.Properties["Encoding"].Value,
                            Value = (byte[])mib.Properties["Value"].Value
                        });
                    }
                    catch
                    {
                    }
                }
                // イベントを発生させるなり連動処理云々
            }
        }

※異常系は省略


【2012.07.24追記】
書き忘れがあったので追記する。


    public class VariableBinding
    {
        /// <summary>
        /// オブジェクト識別子
        /// </summary>
        public string Oid { get; set; }
        /// <summary>
        /// エンコード情報
        /// </summary>
        public string Encoding { get; set; }
        /// <summary>
        /// データ
        /// </summary>
        public byte[] Value { get; set; }
    }





6 件のコメント:

  1. すみません、、
    VariableBindingってカスタムクラスですか?

    返信削除
    返信
    1. 失礼しました。ご指摘ありがとうございます。
      カスタムクラスですが、ただの入れ物です。

      削除
  2. あああ、、、よく見たらstringとbyte[]に型変換してるやん。。
    なんで気づかなかったんだろorz

    わざわざ返信有難うございました。
    ものすっごい参考にさせていただきます。

    返信削除
  3. C#を最近勉強し始めた者です。
    [C#]SNMP Trapのブログのソースをお借りして、デスクトップアプリを開発しています。
    そこで質問したい点があるのですがNETアプリではなく、Windows上でのデスクトップアプリとして使用する為にはどうすればいいのでしょうか?
    よろしくお願いします。

    返信削除
    返信
    1. 上記コードは「NETアプリ」ではなく .NET Framework を使ったアプリケーション、つまり「Windows デスクトップアプリ」ですので、そのまま使用出来ます。

      > どうすればいいのでしょうか?
      ざっくりとした質問なので、回答が的外れだったらすいません。
      とりあえず、
      1.MainWindow.xaml.csにソースを貼付ける(Windows Formsだったらすいません)
      2.起動時にStart()メソッドをCALL
      3.「// イベントを発生させるなり連動処理云々…」て書いてあるところにやりたいことを書く
       ->受信内容を画面上に表示するのであれば、Trapの受信はUIスレッドではありません。
        Dispatcherを介さないと例外が発生しますので注意が必要です。
      という感じでしょうか。さすがに MainWindow.cs に書くのは乱暴なので、SnmpTrap クラスでも作ってこのコードをベースに肉付けしていく形が良いと思いますが。うまく伝わりましたでしょうか?

      削除
    2. 迅速な対応ありがとうございます。
      参考にしてまた頑張っていきます。
      もし、何かありましたら質問等するかも知れませんがよろしくお願いします。

      削除