2011-02-17 32 views
0

私はこのすべてにかなり新しいですが、私は質問を見て、私の質問に答えて何も見つけることができません。なぜNetworkChangeイベントが起動しないのですか

私は、ネットワーク設定が変更されたときにサーバーのいずれかに接続できるかどうかを確認する簡単なサービスを作成しています。

NetworkChangeクラス、NetworkAddressChangedおよびNetworkAvailabiltyChangedの2つのイベントを使用しています。

いずれかのサービスが起動すると、サーバーにpingを実行し、結果に応じてProxyEnableの設定が変更されます。

コード:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Diagnostics; 
using System.Linq; 
using System.ServiceProcess; 
using System.Text; 
using System.Net.NetworkInformation; 
using Microsoft.Win32; 


namespace ProxyManager 
{ 
    public partial class ProxyManager : ServiceBase 
    { 
     static RegistryKey rk = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Internet Settings",true); 
     static string currentProxy = rk.GetValue("ProxyEnable").ToString(); 
     static string newProxy; 

     public ProxyManager() 
     { 
      InitializeComponent(); 

      NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(NetworkChange_NetworkAddressChanged); 
      NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged); 
      newProxy = "0"; 
     } 

     protected override void OnStart(string[] args) 
     { 

     } 

     void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e) 
     { 
      ProxySwitcher(); 
      EventLog evt = new EventLog("ProxyManager"); 
      string message = "Proxy Manager, Newtwork availabilty changed. Proxy switched to " + newProxy.ToString(); 
      evt.Source = "Proxy Manager"; 
      evt.WriteEntry(message,EventLogEntryType.Information); 

     } 

     void NetworkChange_NetworkAddressChanged(object sender, EventArgs e) 
     { 
      ProxySwitcher(); 
      EventLog evt = new EventLog("ProxyManager"); 
      string message = "Proxy Manager, Newtwork address changed. Proxy switched to " + newProxy.ToString(); 
      evt.Source = "Proxy Manager"; 
      evt.WriteEntry(message,EventLogEntryType.Information); 
     } 

     void ProxySwitcher() 
     {  
      if (currentProxy == "0") 
      { 
       newProxy = "1"; 
      } 
      else 
      { 
       newProxy = "0"; 
      } 

      try 
      { 
       Ping myPing = new Ping(); 
       string host = "FILE SERVER"; 
       byte[] buffer = new byte[32]; 
       int timeout = 1000; 
       PingOptions pingOptions = new PingOptions(); 
       PingReply reply = myPing.Send(host, timeout, buffer, pingOptions); 
       if (reply.Status == IPStatus.Success) 
       { 
        if (currentProxy == "0") 
        { 

         rk.SetValue("ProxyEnable", newProxy); 
        } 
       } 
       else 
       { 
        if (currentProxy == "1") 
        { 
         rk.SetValue("ProxyEnable", newProxy); 
        } 
       } 
      } 
      catch (PingException pingEx) 
      { 
       rk.SetValue("ProxyEnable", 0); 
      } 
     } 
     protected override void OnStop() 
     { 
     } 
    } 
} 

私の問題は、サービスがインストールされ、実行されている場合、イベントがいずれかのトリガされていないか、ピックアップされていないということです。関連するイベントが記録されず、プロキシが切り替えられていません。

私は実行可能なコンソールアプリケーションのイベントハンドラを除いたコードを試しましたが、これはネットワークの可用性に応じてうまくいきました。

私はWindows 7 x86を実行していますが、.NET 3.5でコーディングしています。

ご協力いただきありがとうございます。

答えて

1

これはかなり大きなWMIアプリケーションを作成しましたが、これはWMIではうまく動作しませんでした。特にWindows Vista以前のオペレーティングシステムを扱う場合、例外を適切に処理することで、Tedや.NETのWMIサポートには賛成できません。

これらのイベントを処理する際には2つの警告があります。まず、メインスレッドで購読している場合にのみ動作します。ただし、ログファイルが作成されるので、イベントがトリガーされていることを確認したように見えます。 2番目の問題は、コードがネットワークの現在の状態を前提にしていることです。

あなたのコードの外観からは、Proxy = 0で始まるので、プロキシはありません。その後、ネットワーク変更イベントを受け取ると、プロキシを切り替えることができます。サービスが開始され、ネットワークがすでに「ダウン」しているときに何が起こるかを考えてください。ネットワークスタックの初期化に関してサービスがいつ開始するかによって、起動時に非常にうまくいくかもしれません。 NICがダウンしているときは "no proxy"を設定し、NICがアップしているときは "Proxy"を設定します。これはあなたが達成しようとしていたものとは逆のようです。

ネットワークの状態を確認して、変更イベントが発生した理由を知る必要がある場合は、修正が簡単です。したがって、NetworkAvailabilityChangedイベントでは、ループバックまたはmsトンネルではない1つのネットワークインターフェイスが存在する限り、trueを返すNetworkInterface.GetIsNetworkAvailable()をチェックします。

NetworkAddressChangedイベントの場合、アドレスが有効かどうかを確認して、プロキシを呼び出す必要があるかどうかを判断したいと考えられます。

UnicastIPAddressInformationCollectionのようにすることができます。 NetworkInterface [] niList = NetworkInterface.GetAllNetworkInterfaces();

 foreach (NetworkInterface ni in niList) 
     { 
      switch (ni.NetworkInterfaceType) 
      { 
       case NetworkInterfaceType.Ethernet: // 10baseT 
       case NetworkInterfaceType.FastEthernetT: // 100baseT 
       case NetworkInterfaceType.GigabitEthernet: 
        GatewayIPAddressInformationCollection gwIPColl = ni.GetIPProperties().GatewayAddresses; 
        UnicastIPAddressInformation uniIPInfo = null; 
        UnicastIPAddressInformationCollection IPcoll = ni.GetIPProperties().UnicastAddresses; 
        if (IPcoll.Count <= 0) 
        { 
         LogFile.LogMe("No valid unicast IP address"); 
         broken = true; 
         break; // Cannot continue if we don't have an IP in the colletion 
        } 

。 。 。

など、どれくらい複雑にしたいのかによっては同じようなものがあります。ネットワークアドレスの有効性をチェックすると、ユニキャストアドレス、ネットマスク(.IPv4Mask)、ゲートウェイIPAddressInformationCollection(.GetIPProperties()。GatewayAddresses)から定義されたゲートウェイを確認します。

ほんとうに役立ちます。

+1

私はまた、インターフェイスが上がったり下がったりすると、インターフェイスがダウンしたときにIPが0.0.0.0になり、インターフェイスが起動したときに適切なIPに復元するため、これらのイベントの両方が起きると言います。だから、両方のイベントをフックし、両方でProxySwitch()を実行することで、どこにも高速になることはありません。 –

1

イベントログの代わりにファイルにロギングを試みることがあります。イベントログにはアクセス許可の問題があり、サービスを実行しているときに、セキュリティモデルによってユーザーがログに書き込めないことがあります。

+0

もしそうなら、単純なブレークポイントが問題を明らかにします。 –

+0

私はブレークポイントを追加しようとしました。何も起こりません。また、ファイルへのロギングを試みましたが、何もしませんでした。 – Slotty

+0

hmmm ...ちょうど確かに...あなたはイベントログを呼び出す前にファイルに書き込んでいますか?セキュリティ権限エラーの場合、例外をスローします。これにより、コードがファイルに書き込まれないことがあります... – Saibal

1

WMIの使用を検討してください。 いくつかのサンプルVBScriptsについてhttp://msdn.microsoft.com/en-us/library/aa394595(v=vs.85).aspx

私は経験上、WMIは動作していますが、 "NetworkChange"オブジェクトでは試したことがないことを知っています。

+0

現時点ではこれを正解としてマークするにはWMIについて十分に分かりませんが、私は読んで試してみることにします。 – Slotty

+0

WMIは、すべてのOSコントロールがある場所です。マイクロソフトは、Linux/procファイルシステムのようなランダムなAPI呼び出しで拡散させずに、そこに置こうとしました。 .Netには素晴らしいWMIサポートがあります。 WMIには、静的情報(CPU、RAM、OSなど)、動的情報(IP、リソースなど)および購読可能なイベント(変更されたもの)が含まれています。良い視点は、WMICでばかげていることです。 CMDを起動してWMICと入力し、コマンド/?を入力するだけです。そしておそらくコマンドNICCONFIG LIST(後ですべてのフィールドを見るためにスクロール) –

+0

詳細情報をありがとう - これはすべてC#プロジェクト内から呼び出すことができますか? System.Management;を使用します。 – Slotty

関連する問題