Подтвердить что ты не робот

Служба Windows для постоянной работы

Ive создал службу Windows под названием ProxyMonitor и im в настоящее время на этапе установки и удаления службы, как я ее хочу.

Итак, я выполняю приложение следующим образом:

C:\\Windows\\Vendor\\ProxyMonitor.exe /install

Довольно объяснительно, а затем я добрался до services.msc и запустил службу, но когда я это сделаю, я получаю следующее сообщение:

Служба прокси-монитора на локальном компьютере началась, а затем остановлена. Некоторые службы автоматически останавливаются, если нет работы, например, "Журналы производительности и оповещения"

Мой код выглядит так:

public static Main(string[] Args)
{
    if (System.Environment.UserInteractive)
    {
        /*
            * Here I have my install logic
        */
    }
    else
    {
        ServiceBase.Run(new ProxyMonitor());
    }
}

И затем в классе ProxyMonitor у меня есть:

public ProxyMonitor()
{
}

protected override void OnStart(string[] args)
{
    base.OnStart(args);
    ProxyEventLog.WriteEntry("ProxyMonitor Started");

    running = true;
    while (running)
    {
        //Execution Loop
    }
}

и onStop() Я просто изменяю переменную running на false;

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


Обновление: 1

protected override void OnStart(string[] args)
{
     base.OnStart(args);
     ProxyEventLog.WriteEntry("ProxyMonitor Started");

     Thread = new Thread(ThreadWorker);
     Thread.Start();
 }

В ThreadWorker у меня есть ProxyEventLogger.WriteEntry("Main thread entered"), который не срабатывает.

4b9b3361

Ответ 1

Обратный вызов OnStart() должен возвращаться своевременно, поэтому вы хотите начать поток, где будет выполняться вся ваша работа. Я бы рекомендовал добавить в класс следующие поля:

using System.Threading;
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private Thread _thread;

В поле _thread будет содержаться ссылка на объект System.Threading.Thread, который вы создаете в обратном вызове OnStart(). Поле _shutdownEvent содержит конструкцию события на системном уровне, которая будет использоваться для сигнализации о прекращении работы потока при завершении работы службы.

В обратном вызове OnStart() создайте и запустите свой поток.

protected override void OnStart(string[] args)
{
     _thread = new Thread(WorkerThreadFunc);
     _thread.Name = "My Worker Thread";
     _thread.IsBackground = true;
     _thread.Start();
}

Для этого вам нужна функция с именем WorkerThreadFunc. Он должен соответствовать подписке System.Threading.ThreadStart.

private void WorkerThreadFunc()
{
}

Если вы не поместите ничего в эту функцию, поток запустится, а затем сразу же выключится, поэтому вам придется поместить туда некоторую логику, которая в основном сохраняет поток в то время, пока вы выполняете свою работу. Здесь _shutdownEvent пригодится.

private void WorkerThreadFunc()
{
    while (!_shutdownEvent.WaitOne(0)) {
        // Replace the Sleep() call with the work you need to do
        Thread.Sleep(1000);
    }
}

Цикл while проверяет ManualResetEvent, чтобы убедиться, что он установлен или нет. Поскольку мы инициализировали объект с помощью false выше, эта проверка возвращает false. Внутри цикла мы спим в течение 1 секунды. Вы захотите заменить это на работу, которую вы должны выполнить - контролировать настройки прокси-сервера и т.д.

Наконец, в обратном вызове OnStop() вашей Службы Windows вы хотите, чтобы поток прекратил работу. Это легко использовать с помощью _shutdownEvent.

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

Надеюсь, что это поможет.

Ответ 2

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

Edit:

Попробуйте ввести System.Diagnostics.Debugger.Launch() в свой OnStart, чтобы увидеть, что происходит (и поместите точку останова в ThreadWorker). Я бы рекомендовал обернуть это в #if DEBUG, чтобы убедиться, что он не развертывается.

Я просто понял, что вы не дадите свое имя Thread:

 Thread myThread = new Thread(ThreadWorker);
 myThread.Start();

Ответ 3

Конечно, не добавление цикла while в метод OnStart. Это скажет OS, что служба не запущена, потому что она не смогла безопасно выйти из метода OnStart. Обычно я создаю Timer, который включен в методе OnStart. Затем в методе Ticks я вызываю необходимый метод, чтобы заставить аппликацию работать.

В качестве альтернативы вы можете сделать следующее:

// The main entry point for the process 
static void Main() 
{ 
    System.ServiceProcess.ServiceBase[] ServicesToRun; 
    ServicesToRun = new System.ServiceProcess.ServiceBase[] { new WinService1() }; 
    System.ServiceProcess.ServiceBase.Run(ServicesToRun); 
} 

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

Ответ 4

Пример кода, продемонстрированного с помощью консольного приложения. надеюсь, это поможет..

 class Program
{
    private static CancellationTokenSource _cancellationTokenSource;
    private static ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
    private static Thread _serviceStartThread;
    private static Thread _serviceStopThread;

    private static int workcounter = 0;
    static void Main(string[] args)
    {

        _cancellationTokenSource = new CancellationTokenSource();
        _serviceStartThread = new Thread(DoWork);
        _serviceStopThread = new Thread(ScheduledStop);
        StartService();
        StopService();
    }

    private static void StartService()
    {
        _serviceStartThread.Start();

    }

    private static void StopService()
    {
        _serviceStopThread.Start();
    }


    /// <summary>
    /// Triggers a cancellation event for stopping the service in a timely fashion.
    /// </summary>
    private static void ScheduledStop()
    {
        while (!_shutdownEvent.WaitOne(0))
        {
            if (workcounter == 10)
            {
                _cancellationTokenSource.Cancel();
            }
        }
    }

    /// <summary>
    /// Represents a long running Task with cancellation option
    /// </summary>
    private static void DoWork()
    {

        while (!_shutdownEvent.WaitOne(0))
        {
            if(!_cancellationTokenSource.Token.IsCancellationRequested)
            {
                workcounter += 1;
                Console.Write(Environment.NewLine);
                Console.Write("Running...counter: " + workcounter.ToString());
                Thread.Sleep(1000);//Not needed, just for demo..
            }
            else
            {
                Console.Write(Environment.NewLine);
                Console.Write("Recieved cancellation token,shutting down in 5 seconds.. counter: " + workcounter.ToString());
                _shutdownEvent.Set();
                Thread.Sleep(5000);//Not needed, just for demo..
            }

        }
    }
}

Ответ 5

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