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

Запустите консольное приложение как службу

Я разработал приложение С#, в котором тип вывода apllication - Консольная аппликация. Я хочу запустить это приложение как службу. Environment.UserInteractive всегда прав, когда я запускаю его из визуальной студии или просто дважды нажимаю на .exe.

Ниже мой код

 static void Main(string[] args)
        {
            // Get the version of the current application.
            Assembly assem = Assembly.GetExecutingAssembly();
            AssemblyName assemName = assem.GetName();
            Version ver = assemName.Version;
            // Console.WriteLine("{0}, Version {1}", assemName.Name, ver.ToString());

            Console.WriteLine("{0} version {1}", assemName.Name, ver.ToString());

            TouchService touchService = new TouchService();


            if (Environment.UserInteractive)
            {
                bool show_help = false;
                bool install_service = false;
                bool uninstall_service = false;
                string servicename = "";

                OptionSet p = new OptionSet()                  
                  .Add("h|?|help", delegate(string v) { show_help = v != null; })
                  .Add("s|servicename=", "name of installed service", delegate(string v) { servicename = v; })
                  .Add("i|install", "install program as a Windows Service. A valid servicename is needed.", delegate(string v) { install_service = v != null; })
                  .Add("u|uninstall", "uninstall program from Windows Services. A valid servicename is needed.", delegate(string v) { uninstall_service = v != null; });

                List<string> extra;
                try
                {
                    extra = p.Parse(args);
                }
                catch (OptionException e)
                {
                    Console.Write("TouchServer: ");
                    Console.WriteLine(e.Message);
                    Console.WriteLine("Try `TouchServer --help' for more information.");
                    return;
                }

                if (show_help)
                {
                    ShowHelp(p);
                    return;
                }

                else if (install_service)
                {
                    IntegratedServiceInstaller Inst = new IntegratedServiceInstaller();
                    Inst.Install(servicename, null, "Provides XML data over HTTP for Touch clients",                                                              
                                 System.ServiceProcess.ServiceAccount.NetworkService,
                                 System.ServiceProcess.ServiceStartMode.Manual);

                    return;
                }

                else if (uninstall_service)
                {
                    IntegratedServiceInstaller Inst = new IntegratedServiceInstaller();
                    Inst.Uninstall(servicename);
                    return;
                }

                // start and run the server,
                // and receive commands from the console
                else
                {

                    touchService.OnStart(args);                   
                    while(true)
                    {
                        Console.Write("TouchServer>");                        
                        string commandLine = Console.ReadLine().ToLower();

                        if (commandLine == "exit" || commandLine == "x")
                        {
                            break;
                        }
                        if (commandLine == "quit" || commandLine == "q")
                        {
                            break;
                        }

                        else if(commandLine == "version" || commandLine == "v")
                        {
                            Console.WriteLine("{0} version {1}", assem.GetName().Name, assem.GetName().Version.ToString());
                        }

                        else if (commandLine == "list" || commandLine == "l")
                        {
                            TouchServer.showURLs = (TouchServer.showURLs == false) ? true : false; 
                            Console.WriteLine("List URLs: {0}", (TouchServer.showURLs ? "active" : "inactive"));
                        }

                        else if (commandLine == "status" || commandLine == "s")
                        {
                            Console.WriteLine("{0,-20} {1,8}", "Name", "Sessions");                            
                            Console.WriteLine("----------------------------");
                            foreach (Site site in TouchServer.siteCollection.All)
                            {
                                Console.WriteLine("{0,-20} {1,8}", site.Name, site.AllSessions.Length);
                            }
                            Console.WriteLine();
                        }
                    }

                    touchService.OnStop();
                }
            }
            **else
            {
                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[] 
                { 
                    new TouchService() 
                };
                ServiceBase.Run(ServicesToRun);
            }**

Как я могу запустить его как услугу, пожалуйста, помогите мне. заранее спасибо Сангита

4b9b3361

Ответ 1

Используйте Файл- > Новый проект- > Visual С# → Windows- > Сервис Windows,

И добавьте свой основной код в обработчики событий OnStart() и OnStop(), затем установите его как службу:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;

namespace MyWindowsService
{
    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
        }

        protected override void OnStop()
        {
        }
    }
}

Ответ 2

Вот решение, которое я использовал, оно прекрасно работает в Visual Studio 2012 и .NET 4.5. Когда я запускаю консольный режим, он отлично работает, и когда я запускаю службу с помощью installutil.exe, он отлично работает.

Основной файл

Файл MainPayload.cs. Вы можете игнорировать все другие файлы и вставлять свой длинный код в этот файл. Обратите внимание на CancellationTokenSource, поэтому ваш сервис может быстро выйти из службы, когда служба перестанет работать.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
//using Gurock.SmartInspect; // Only used if we are logging using SmartInspect (see www.SmartInspect.com).
namespace Demos___Service_Plus_Console
{
    /// <summary>
    /// Main entry point for both console and Windows service.
    /// </summary>
    public class MainPayload
    {
        private readonly CancellationTokenSource _cancellationTokenSource;

        /// <summary>
        /// Constructor; do not block in this call; it is for setup only.
        /// </summary>
        public MainPayload(CancellationTokenSource cancellationTokenSource)
        {
            // Do not block in this call; it is for setup only.
            _cancellationTokenSource = cancellationTokenSource;
        }   
        /// <summary>
        /// Long running task here.
        /// </summary>
        public void Run()
        {
            while (_cancellationTokenSource.IsCancellationRequested == false)
            {
                //SiAuto.Main.LogMessage(".");
                Console.WriteLine(".");

                // This will break every N seconds, or immediately if on cancellation token.
                _cancellationTokenSource.Token.WaitHandle.WaitOne(TimeSpan.FromSeconds(1));
            }
            //SiAuto.Main.LogMessage("Exited Run().");
            Console.WriteLine("Exited Run().");
            Thread.Sleep(500); // If we remove this line, then we will miss the final few writes to the console.
        }
    }
}

Поддержка файлов

Файл EntryPoint.cs. Это точка входа как для консольного приложения, так и для службы.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
//using Gurock.SmartInspect; // Only used if we are logging using SmartInspect (see www.SmartInspect.com).
namespace Demos___Service_Plus_Console
{
    internal static class EntryPoint
    {
        // Run in console mode.
        private static readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
        private static Task _task;

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        public static void Main(string[] args)
        {
            //SiAuto.Si.Connections = "pipe(reconnect=\"true\", reconnect.interval=\"10\", backlog.enabled=\"true\", backlog.flushon=\"debug\", backlog.keepopen=\"true\")";
            //SiAuto.Si.Enabled = true;

            if (Environment.UserInteractive)
            {
                // Make sure that we can write to the console.
                StreamWriter standardOutput = new StreamWriter(Console.OpenStandardOutput()) {AutoFlush = true};
                Console.SetOut(standardOutput);

                // If Ctrl-C is pressed in the console, we get to here.
                Console.CancelKeyPress += new ConsoleCancelEventHandler(myHandler);

                MainPayload myMain = new MainPayload(_cancellationTokenSource); // Pass the token into the task.
                _task = Task.Run(() => myMain.Run());

                // Wait for the payload task to finish.
                while (_cancellationTokenSource.IsCancellationRequested == false)
                {
                    // This will break every N seconds, or immediately if cancellation token is pinged.
                    _cancellationTokenSource.Token.WaitHandle.WaitOne(TimeSpan.FromSeconds(10));
                }
            }
            else
            {
                // Run as Windows Service.
                var ServicesToRun = new ServiceBase[]
                    {
                        new ServiceController()
                    };
                ServiceBase.Run(ServicesToRun);
            }

            _task.Wait(TimeSpan.FromSeconds(10)); // Delay for console to write its final output.
        }

        static void myHandler(object sender, ConsoleCancelEventArgs args)
        {
            _cancellationTokenSource.Cancel();
            //SiAuto.Main.LogMessage("CtrlC pressed.");
            Console.WriteLine("CtrlC pressed.");
        }
    }
}

Файл ProjectInstaller.cs. Это установщик для службы.

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using System.Threading.Tasks;

namespace Demos___Service_Plus_Console
{
    [RunInstaller(true)]
    public partial class ProjectInstaller : System.Configuration.Install.Installer
    {
        public ProjectInstaller()
        {
            InitializeComponent();
        }

        private void serviceInstaller1_AfterInstall(object sender, InstallEventArgs e)
        {

        }

        private void serviceProcessInstaller1_AfterInstall(object sender, InstallEventArgs e)
        {

        }
    }
}

Файл ServiceController.cs. Это содержит методы Start() и Stop() для службы.

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.Threading;
using System.Threading.Tasks;

namespace Demos___Service_Plus_Console
{
    /// <summary>
    /// When running in service mode.
    /// </summary>
    public partial class ServiceController : ServiceBase
    {
        public ServiceController()
        {
            InitializeComponent();
        }

        readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

        // Initialize payload.
        private MainPayload myMain;

        protected override void OnStart(string[] args)
        {
            myMain = new MainPayload(cancellationTokenSource); // Pass the token into the task.
            Task.Run(() => myMain.Run());
        }

        protected override void OnStop()
        {
            cancellationTokenSource.Cancel();
        }
    }
}

Как установить службу Windows

Чтобы установить это как службу Windows, используйте installutil.exe ServiceName.exe. Для удаления используйте installutil.exe ServiceName.exe -u. Это означает, что вам нужно будет открыть Visual Studio 2012 x32 command prompt, который находится под Visual Studio Tools в Start Menu. Если вы компилируете в 32-битном режиме, используйте 32-битную командную строку, и если вы компилируете в 64-битном режиме, откройте 64-битную командную строку (это означает, что пути настроены правильно, как installutil.exe имеет отдельные версии в зависимости от того, является ли его 32-разрядная или 64-разрядная версия).

Откройте панель Services, затем найдите новую службу с именем ServiceController. Когда вы запустите его, если вы включили фреймворк регистрации, вы увидите, что в журнале каждый раз появляются сообщения.

Как я создал этот код

Он выглядит как много кода, но его все основывается на шаблоне проекта Windows Service в Visual Studio 2012. Я создал новую службу Windows, а затем использовал Environment.UserInteracive для переключения между консолью или службой. Я добавил CancellationTokens, чтобы убедиться, что если служба была остановлена, задача также быстро прекратится (даже если она была в задержке).

Единственный трюк - щелкнуть правой кнопкой мыши на сером фоне страницы "Service1.cs", затем нажать "Добавить установщик" , который добавит установщик. Если вы этого не сделаете, то installutil.exe выдаст вам ошибку.

enter image description here

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

Вот требуемые дополнительные ссылки (они автоматически добавляются при создании новой службы Windows с использованием шаблона):

  • System.ServiceProcess
  • System.Configuration.Install

Вы увидите ссылки на Gurock.SmartInspect и SiAuto. Если вы хотите наблюдать журналы, созданные запущенной службой, вы можете использовать это или что-то еще, например NLog или log4net.

Ответ 3

Environment.UserInteractive является ложным только тогда, когда он фактически работает как служба. Когда вы дважды щелкните по нему или запустите его из Visual Studio; он работает как обычное консольное приложение, и для него доступен рабочий стол, поэтому Environment.UserInteractive имеет значение true.

Вы можете получить свой класс из класса ConsoleService Основание кода Squiggle, чтобы создать консольное приложение, которое также может работать как служба Windows.

public class ConsoleService : ServiceBase
{
    public void RunConsole(string[] args)
    {
        Trace.Listeners.Add(new ConsoleTraceListener());
        OnStart(args);
        Trace.WriteLine(this.ServiceName + " running... Press any key to stop");
        Trace.WriteLine("");
        Console.ReadKey();
        OnStop();
    }

    public static void Run<TService>(string[] args) where TService : ConsoleService, new()
    {
        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
        if (Environment.UserInteractive)
        {
            try
            {
                string option = args.Length > 0 ? args[0].ToUpperInvariant() : String.Empty;
                switch (option)
                {
                    case "-I":
                    case "/I":
                        ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetCallingAssembly().Location });
                        break;
                    case "-U":
                    case "/U":
                        ManagedInstallerClass.InstallHelper(new string[] { "/U", Assembly.GetCallingAssembly().Location });
                        break;
                    default:
                        new TService().RunConsole(args);
                        break;
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
            }
        }
        else
        {
            ServiceBase[] servicesToRun = new ServiceBase[] { new TService() };
            ServiceBase.Run(servicesToRun);
        }
    }

    static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        if (e.ExceptionObject is Exception)
            Trace.WriteLine(((Exception)e.ExceptionObject).Message);
    }
}

Ответ 4

Я только что протестировал это в Visual Studio 2013, и он работает.

  • Создайте новый проект "Служба Windows".
  • Измените тип вывода проекта на "Консольное приложение"

Вот как выглядит моя Program.cs:

static class Program
{
  /// <summary>
  /// </summary>
  static void Main()
  {
    if (!Environment.UserInteractive)
    {
      ServiceBase[] ServicesToRun;
      ServicesToRun = new ServiceBase[] 
          { 
              new Service1() 
          };
      ServiceBase.Run(ServicesToRun);
    }
    else
    {
      Console.Write("Hit any key to continue...");
      Console.ReadKey();
    }
  }
}

Вы можете добавить сервисную установку как это

Вы можете установить службу с помощью этой команды: installutil.exe /i YouExeName.exe

Вы можете удалить службу с помощью этой команды: installutil.exe /u YouExeName.exe