简体   繁体   中英

Why won't NetworkChange events fire

I am fairly new to all this but I have looked through questions and can't find anything that answers my question.

I am writing a simple service that checks whether it can reach one of our servers whenever there is a change to it's network settings.

I am using the two events under the NetworkChange class, NetworkAddressChanged and NetworkAvailabiltyChanged.

When either fire the service tries to ping the server and depending on the result changes the ProxyEnable setting.

The Code:

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()
        {
        }
    }
}

My problem is that when the service is installed and running, the events are either not being triggered or not being picked up. There related events are not being logged and the proxy is not switching.

I tried the code, minus the event handlers in a console app that I could run at will and that worked fine, depending on the network availability.

I am running Windows 7 x86, but am coding in .NET 3.5.

Any help will be gratefully received.

I wrote a rather large WMI application and this is the one feature that I could never get to work well with WMI. Sorry to disagree with Ted but .NET WMI support is terrible, particularly with dealing with exceptions properly and when dealing with pre-Vista operating systems.

Two caveats when dealing with these events. First, they only work if subscribed on the main thread. However, since your log file gets created then you appear to have verified that the event is being triggered. The second problem is in the assumption your code makes about the current state of the network.

From the look of your code you are starting with Proxy = 0, so no proxy. Then when you receive a network change event you toggle the proxy. Consider what happens when your service starts and the network is "down" already, which might very well happen during bootup depending on when your service starts in relation to the network stack initialization. You will be setting "no proxy" when the NIC is down, then setting "Proxy" when the NIC is up. This seems to be inverted to what you were trying to accomplish.

The fix is simple, in the event you need to check the state of the network to know why the change event was fired. So, in your NetworkAvailabilityChanged event you are going to want to check NetworkInterface.GetIsNetworkAvailable() which returns true as long as there is one network interface that isn't loopback or ms-tunnel.

For the NetworkAddressChanged event presumably you are going to want to check the address to see if it's valid or not to determine if your proxy needs to be invoked. You can do this by grabbing the

UnicastIPAddressInformationCollection like this... 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
                    }

. . .

or something similar depending on how complicated your want to make it. When I check for network address validity I check the Unicast address, Netmask (.IPv4Mask) and the defined gateway from GatewayIPAddressInformationCollection (.GetIPProperties().GatewayAddresses)

Hopefully that helps you out a little bit.

You may try logging to a file instead of the event log. There are permission issues with the event log and when you are running the service, the security model may be preventing you from writing to the log.

Consider using WMI. Some sample VBScripts on http://msdn.microsoft.com/en-us/library/aa394595(v=vs.85).aspx

I know from experience that WMI works, but never tried it with "NetworkChange" object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM