Windows сервис для мониторинга изменений сетевого интерфейса


В настоящее время я работаю над несколькими проектами для своей компании, чтобы помочь уменьшить количество вызовов приходится иметь дело с так что мы можем сосредоточиться на более приоритетных задач, таких как сокращение ресурсов сервера и т. д.

Первый проект в моем списке было уменьшить количество вопросов прокси-у пользователя при переходе из внутренней сети к внешней сети, такой как интернет.

Я пришел с идеей служба Windows, где служба будет развернута с нашего сервера и установить через команду. После установки и запуска службы будет следить за государствами подключения всех сетевых интерфейсов на компьютере.

При изменении сетевого интерфейса, таких как:

  • Сети Ethernet подключить
  • IP меняется
  • Интерфейсы включен / отключен
  • и т. д.

служба будет пытаться пинговать наш Контроллер_домена. Если пинг прошел успешно, то мы будем проверять, чтобы увидеть, если параметры прокси-сервера для машины устанавливаются. Если нет, то мы автоматически установит их и даст им. Если проверка завершается неудачей, мы отключаем прокси.

Проект не полностью завершен, но есть еще хороший кусок кода для проверки.

ProxyMonitor.в CS

using System;
using System.Diagnostics;
using System.ServiceProcess;
using System.Configuration.Install;
using System.Reflection;
using System.Threading;
using System.Net.NetworkInformation;

namespace Serco.Services.ProxyMonitor
{
    class ProxyMonitor : ServiceBase
    {
        static void Main(string[] args) 
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;
            if (System.Environment.UserInteractive)
            {
                string parameter = string.Concat(args);
                switch (parameter)
                {
                    case "/install":
                            ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });
                        break;
                    case "/uninstall":
                        ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
                        break;
                }
            }
            else
            {
                ServiceBase.Run(new ProxyMonitor());
            }
        }

        private static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
        }

        /*
         * Start the main service application
         */
        private ManualResetEvent MainShutdownEvent = new ManualResetEvent(false);
        private Thread MainThread;
        private static EventLog EventManager = new EventLog();
        public static string ProxyIp;

        public ProxyMonitor()
        {
            EventManager.Source = ServiceConfiguration.ServiceName;
        }

        protected override void OnStart(string[] args)
        {
            ProxyIp = string.Concat(args);
            MainThread = new Thread(MainWorkerThread);
            MainThread.Name = "MainWorkerThread";
            MainThread.IsBackground = true;
            MainThread.Start();
        }

        private void MainWorkerThread()
        {
            EventManager.WriteEntry("Watching for ip: " + ProxyIp);
            NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(AddressChangedCallback);
        }

        public static void AddressChangedCallback(object Sender,EventArgs Args)
        {
            //try and ping the Proxy Server
            Ping Ping = new Ping();
            PingReply Reply = Ping.Send("secret.domain");

            if (Reply.Status == IPStatus.Success) 
            {
                /*
                 * Update Proxy Settings
                 */
            }
        }

        protected override void OnStop()
        {
            MainShutdownEvent.Set();
            if(!MainThread.Join(3000))
            {
                // give the thread 3 seconds to stop
                MainThread.Abort();
            }
        }
    }
}

ManagedInstallation.в CS

using System;
using System.ServiceProcess;
using System.Configuration;
using System.ComponentModel;
using System.Configuration.Install;

namespace Serco.Services.ProxyMonitor
{
    [RunInstaller(true)]
    public class ManagedInstallation : Installer
    {
        public ManagedInstallation()
        {
            var ProcessInstaller = new ServiceProcessInstaller();
            var ServiceInstaller = new ServiceInstaller();

            //set the information and privileges
            ProcessInstaller.Account        = ServiceConfiguration.AccountType;
            ProcessInstaller.Username       = null;
            ProcessInstaller.Password       = null;
            ServiceInstaller.DisplayName    = ServiceConfiguration.DisplayName;
            ServiceInstaller.StartType      = ServiceConfiguration.StartType;
            ServiceInstaller.Description    = ServiceConfiguration.Description;
            ServiceInstaller.ServiceName    = ServiceConfiguration.ServiceName;

            Installers.Add(ProcessInstaller);
            Installers.Add(ServiceInstaller);
        }

        private ServiceController ServiceController = new ServiceController(ServiceConfiguration.ServiceName);

        protected override void OnAfterInstall(System.Collections.IDictionary savedState)
        {
            base.OnAfterInstall(savedState);
            ServiceController.Start();
        }
    }
}

Файл serviceconfiguration.в CS

using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceProcess;

namespace Serco.Services.ProxyMonitor
{
    class ServiceConfiguration
    {
        public static string DisplayName
        {
            get { return "Proxy Monitor"; }
        }

        public static string ServiceName
        {
            get { return "ProxyMonitor"; }
        }

        public static string Description
        {
            get
            {
                return "ProxyMonitor is a helper developed to manage the state of the proxy for the employess whilst of the internal network.";
            }
        }

        public static ServiceStartMode StartType
        {
            get{return ServiceStartMode.Automatic;}
        }

        public static ServiceAccount AccountType 
        {
            get{return ServiceAccount.LocalSystem;}
        }
    }
}

В файл serviceconfiguration класс может быть изменен, чтобы заполнить из локального файла в зависимости от развертывания дискуссии у меня будет с моим колледжей.



2783
9
задан 1 февраля 2011 в 11:02 Источник Поделиться
Комментарии
3 ответа

Просто несколько моментов, которые пришли на ум, когда я читал ваш код.


  • Мне кажется, что основной поток завершается после того, как NetworkChange.NetworkAddressChanged события на крючок, в этом случае поток является избыточным, так как событие будет вызываться в другом потоке в любом случае.

  • MainShutdownEvent создается и "набор", но я не вижу ничего на самом деле использовать его.

  • NetworkChange.NetworkAddressChanged зацепили, но не отцепится, это не имеет большого значения, когда домен приложения выгружается на увольнении, но мне было бы намного лучше, если он был частью стандартного "выключение" процесс в методе onStop()

  • Я не люблю пустые события unhandledexception обработчик событий, если вы намерены подключить его, я хотел бы предложить некоторую форму ведения журнала. Как минимум вы должны использовать журнал таких событий в журнал событий с помощью журнала событий свойство класса servicebase.

  • Я не уверен, какой поток будет использоваться для Рэ в NetworkChange.NetworkAddressChanged, но я бы не стал полагаться на это же, как то onStop() так что вы, вероятно, следует искать в иной форме замок/сигнализация для обработки любых ситуациях, где то onStop() вызывается, когда обработчик событий работает. Это может не вызывать никаких реальных проблем, но я лично хотел бы перестраховаться. Это может быть интересно, чтобы временно добавить долгий сон в обработчик событий, чтобы увидеть, что произойдет, если он занят, когда сказал, чтобы остановить.

6
ответ дан 4 февраля 2011 в 09:02 Источник Поделиться

Я бы порекомендовал посмотреть на обработку исключений в коде - нет ничего, кроме пустой CurrentDomainExceptionHandler. Однако это очень важно для таких услуг, иметь четкое исключение иерархия и Политика обработки. Там должно быть как минимум 2 вида:


  • Неустранимые ошибки - если сервис не смог запустить из-за неверной конфигурации и т. д.

  • Исправимые ошибки - если вы не смогли понг "секрет.домен", так как она недоступна, то вам следует поступить? Как бороться с исключениями тайм-аут? Должны ли быть в очереди с unproceeded запросы или они должны сразу выбрасывать? Если размер очереди может быть настроен, если вам это нужно? Если вы хотите, чтобы ваши услуги работать в режиме 24х7, то вы должны иметь ответы на эти и некоторые другие вопросы о том, как справиться с неожиданными ситуациями.

Еще отсутствует пункт Настройки. Ты собираешься переписать свой код и заново установить, если "секрет.домен" изменения? Или если вам нужно увеличить тайм-аут или даже изменить отображаемое имя службы? Я бы рекомендовал иметь файл конфигурации, который можно перечитывать на каждом старте. Это позволит сэкономить вам много времени.

4
ответ дан 5 февраля 2011 в 09:02 Источник Поделиться

Рассмотрите возможность использования TopShelf управлять всей установка/удаление/настройка службы задач.

Эта замечательная особенность позволяет отлаживать код из командной строки, вместо того, чтобы приложить к службе Windows.

2
ответ дан 3 марта 2011 в 11:03 Источник Поделиться