运行控制台应用程序作为服务

use*_*526 14 c# console

我开发了c#application,其中apllication输出类型是Console Applicatiuon.我想将此应用程序作为服务运行.当我从visual studio运行它或只需双击.exe时,Environment.UserInteractive始终为true.

以下是我的代码

 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);
            }**
Run Code Online (Sandbox Code Playgroud)

我如何将其作为服务运行,请帮助我.在此先感谢sangita

Art*_*fin 16

使用文件 - >新建项目 - > Visual C# - > 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()
        {
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Con*_*ngo 7

这是我使用的解决方案,它在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.
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

支持文件

档案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.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

档案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)
        {

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

档案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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如何安装为Windows服务

要将其安装为Windows服务,请使用installutil.exe ServiceName.exe.要卸载,请使用installutil.exe ServiceName.exe -u.这意味着,你将不得不打开一个Visual Studio 2012 x32 command prompt是下Visual Studio ToolsStart Menu.如果要在32位模式下进行编译,请使用32位命令提示符,如果要在64位模式下进行编译,请打开64位命令提示符(这意味着路径设置正确,并且installutil.exe具有单独的版本取决于它的32位还是64位).

打开Services面板,然后查找名为的新服务ServiceController.当你启动它时,如果你打开了一个日志记录框架,那么你会看到每秒都会记录到日志中的消息.

我是如何创建此代码的

它看起来像很多代码,但它都基于Windows ServiceVisual Studio 2012中的项目模板.我创建了一个新的Windows服务,然后用于Environment.UserInteracive在控制台或服务之间切换.我添加了CancellationTokens以确保如果服务停止,任务也会快速停止(即使它是一个延迟).

唯一的另一个技巧是右键单击"Service1.cs"页面的灰色背景,然后单击"添加安装程序",添加安装程序.如果你不这样做,那么installutil.exe会给你一个错误.

在此输入图像描述

您还必须右键单击serviceProcessInstaller1然后选择Properties并设置AccountLocalService,否则它将在您安装服务时询问您的用户名凭据.

以下是所需的额外引用(使用模板创建新的Windows服务时会自动添加这些引用):

  • System.ServiceProcess
  • System.Configuration.Install

你会注意到Gurock.SmartInspect和的引用SiAuto.如果要观察正在运行的服务创建的日志,可以使用此或其他内容,如NLog或log4net.


Muh*_*han 5

仅当Environment.UserInteractive实际作为服务运行时,它才为false.双击它或从Visual Studio启动它时; 它作为普通的控制台应用程序运行,桌面可用,因此Environment.UserInteractive为true.

您可以从Squiggle代码库的 ConsoleService类派生您的类,以创建一个也可以作为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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*sen 5

我刚刚在Visual Studio 2013中对此进行了测试,并且可以正常工作。

  1. 创建新的“ Windows Service”项目。
  2. 将项目输出类型更改为“控制台应用程序”

这是我的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();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

您可以像这样添加服务安装

您可以使用以下命令安装服务: installutil.exe /i YouExeName.exe

您可以使用以下命令来卸载服务: installutil.exe /u YouExeName.exe