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

Консольное приложение .NET как служба Windows

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

Может кто-то может предложить библиотеку классов или фрагмент кода, который мог бы быстро и легко преобразовать консольное приложение С# в службу?

4b9b3361

Ответ 1

Обычно я использую следующий techinque для запуска того же приложения, что и консольное приложение или как служба:

public static class Program
{
    #region Nested classes to support running as service
    public const string ServiceName = "MyService";

    public class Service : ServiceBase
    {
        public Service()
        {
            ServiceName = Program.ServiceName;
        }

        protected override void OnStart(string[] args)
        {
            Program.Start(args);
        }

        protected override void OnStop()
        {
            Program.Stop();
        }
    }
    #endregion

    static void Main(string[] args)
    {
        if (!Environment.UserInteractive)
            // running as service
            using (var service = new Service())
                ServiceBase.Run(service);
        else
        {
            // running as console app
            Start(args);

            Console.WriteLine("Press any key to stop...");
            Console.ReadKey(true);

            Stop();
        }
    }

    private static void Start(string[] args)
    {
        // onstart code here
    }

    private static void Stop()
    {
        // onstop code here
    }
}

Environment.UserInteractive обычно применяется для консольного приложения и false для службы. Технически, можно запустить службу в интерактивном режиме, поэтому вы можете вместо этого проверить ключ командной строки.

Ответ 2

У меня был большой успех с TopShelf.

TopShelf - это пакет Nuget, предназначенный для упрощения создания приложений .NET Windows, которые могут запускаться как консольные приложения или как службы Windows. Вы можете быстро подключать такие события, как ваша служба. Начать и останавливать события, настроить с помощью кода, например. настроить учетную запись, выполняемую как, настроить зависимости от других служб и настроить, как она восстанавливается из-за ошибок.

В консоли диспетчера пакетов (Nuget):

Установить верхнюю панель пакета

Чтобы начать, обратитесь к

TopShelf также заботится об установке сервиса, что может сэкономить много времени и удалить шаблонный код из вашего решения. Чтобы установить ваш .exe в качестве службы, вы просто выполните из командной строки следующее:

myservice.exe install -servicename "MyService" -displayname "My Service" -description "This is my service."

Вам не нужно подключать ServiceInstaller и все такое - TopShelf делает все для вас.

Ответ 3

Итак, вот полное пошаговое руководство:

  • Создайте новый проект приложения консоли (например, MyService)
  • Добавьте две ссылки библиотек: System.ServiceProcess и System.Configuration.Install
  • Добавьте три файла, напечатанных ниже
  • Создайте проект и запустите "InstallUtil.exe c:\path\to\MyService.exe"
  • Теперь вы должны увидеть MyService в списке услуг (запустите services.msc)

* InstallUtil.exe обычно можно найти здесь: C:\windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.ex e

Program.cs

using System;
using System.IO;
using System.ServiceProcess;

namespace MyService
{
    class Program
    {
        public const string ServiceName = "MyService";

        static void Main(string[] args)
        {
            if (Environment.UserInteractive)
            {
                // running as console app
                Start(args);

                Console.WriteLine("Press any key to stop...");
                Console.ReadKey(true);

                Stop();
            }
            else
            {
                // running as service
                using (var service = new Service())
                {
                    ServiceBase.Run(service);
                }
            }
        }

        public static void Start(string[] args)
        {
            File.AppendAllText(@"c:\temp\MyService.txt", String.Format("{0} started{1}", DateTime.Now, Environment.NewLine));
        }

        public static void Stop()
        {
            File.AppendAllText(@"c:\temp\MyService.txt", String.Format("{0} stopped{1}", DateTime.Now, Environment.NewLine));
        }
    }
}

MyService.cs

using System.ServiceProcess;

namespace MyService
{
    class Service : ServiceBase
    {
        public Service()
        {
            ServiceName = Program.ServiceName;
        }

        protected override void OnStart(string[] args)
        {
            Program.Start(args);
        }

        protected override void OnStop()
        {
            Program.Stop();
        }
    }
}

MyServiceInstaller.cs

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

namespace MyService
{
    [RunInstaller(true)]
    public class MyServiceInstaller : Installer
    {
        public MyServiceInstaller()
        {
            var spi = new ServiceProcessInstaller();
            var si = new ServiceInstaller();

            spi.Account = ServiceAccount.LocalSystem;
            spi.Username = null;
            spi.Password = null;

            si.DisplayName = Program.ServiceName;
            si.ServiceName = Program.ServiceName;
            si.StartType = ServiceStartMode.Automatic;

            Installers.Add(spi);
            Installers.Add(si);
        }
    }
}

Ответ 4

Вы можете использовать

reg add HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run /v ServiceName /d "c:\path\to\service\file\exe"

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

Существует несколько оболочек служб, которые могут запускать любое приложение в качестве реального сервиса. Для примера Microsoft SrvAny из ресурса Win2003 Resource Kit

Ответ 5

Я слышал, что вы хотите, чтобы одна сборка остановила повторный код, но это было бы проще и уменьшить повторение кода и упростить повторное использование вашего кода другими способами в будущем, если... вы разделите его на 3 сборки.

  • Одна сборка библиотеки, которая выполняет всю работу. Тогда у вас есть два очень тонких/простых проекта:
  • который является командной строкой
  • тот, который является службой Windows.

Ответ 6

Во-первых, я внедряю решение консольного приложения в решение для службы Windows и ссылаюсь на него.

Затем я создаю консольное приложение. Класс программы public

/// <summary>
/// Hybrid service/console application
/// </summary>
public class Program
{
}

Затем я создаю две функции в консольном приложении

    /// <summary>
    /// Used to start as a service
    /// </summary>
    public void Start()
    {
        Main();
    }

    /// <summary>
    /// Used to stop the service
    /// </summary>
    public void Stop()
    {
       if (Application.MessageLoop)
            Application.Exit();   //windows app
        else
            Environment.Exit(1);  //console app
    }

Затем в самой службе windows я создаю экземпляр программы и вызываю функции Start и Stop, добавленные в OnStart и OnStop. См. Ниже

class WinService : ServiceBase
{
    readonly Program _application = new Program();

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
        ServiceBase[] servicesToRun = { new WinService() };
        Run(servicesToRun);
    }

    /// <summary>
    /// Set things in motion so your service can do its work.
    /// </summary>
    protected override void OnStart(string[] args)
    {
        Thread thread = new Thread(() => _application.Start());
        thread.Start();
    }

    /// <summary>
    /// Stop this service.
    /// </summary>
    protected override void OnStop()
    {
        Thread thread = new Thread(() => _application.Stop());
        thread.Start();
    }
}

Этот подход также может быть использован для гибридного сервиса windows/windows

Ответ 7

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

"сохранить консольное приложение как один проект"

Однажды я был на вашем месте, превратив консольное приложение в службу. Сначала вам нужен шаблон, если вы работаете с VS Express Edition. Вот ссылка, где вы можете сделать первые шаги: С# Windows Service, это было очень полезно для меня. Затем, используя этот шаблон, добавьте свой код в нужные события службы.

Чтобы улучшить обслуживание, вы можете сделать еще одну вещь, но это не быстро и/или легко, использует приложения и создает dll для загрузки/выгрузки. В одном вы можете запустить новый процесс с помощью консольного приложения, а в другой dll вы можете просто добавить функциональность, которую служба должна выполнить.

Удачи.

Ответ 8

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

Как видно, при запуске Windows многие сервисы, составляющие инфраструктуру, не могут (и не могут напрямую) предоставлять консольные окна пользователю. Служба должна взаимодействовать с пользователем не графически: через SCM; в журнале событий, в некоторый файл журнала и т.д. Службе также необходимо будет связываться с окнами через SCM, иначе он будет отключен.

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

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

Я не читал его полностью, но эта статья кажется пинтой в правильном направлении.