.NET控制台应用程序作为Windows服务

我有控制台应用程序,并希望将其作为Windows服务运行。 VS2010有项目模板,可以连接控制台项目和构buildWindows服务。 我不想添加分离的服务项目,并且如果可能的话,将服务代码集成到控制台应用程序中,以将控制台应用程序保持为可作为控制台应用程序运行的项目,或者如果例如通过使用开关的命令行运行,

也许有人可以build议类库或代码片断,可以快速,轻松地将C#控制台应用程序转换为服务?

我通常使用以下技术来运行相同的应用程序作为控制台应用程序或服务:

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对于控制台应用程序通常为true,对于服务为false。 从技术上讲,可以在用户交互模式下运行服务,因此您可以改为查看命令行开关。

TopShelf取得了巨大的成功。

TopShelf是一个Nuget软件包,用于创build可以作为控制台应用程序或Windows服务运行的.NET Windows应用程序。 您可以快速挂接事件,如服务“启动”和“停止”事件,使用代码进行configuration,例如设置运行的帐户,configuration其他服务的依赖关系以及configuration其从错误中恢复的方式。

从软件包pipe理器控制台(Nuget):

安装包顶部框架

请参阅代码示例以开始。

例:

 HostFactory.Run(x => { x.Service<TownCrier>(s => { s.ConstructUsing(name=> new TownCrier()); s.WhenStarted(tc => tc.Start()); s.WhenStopped(tc => tc.Stop()); }); x.RunAsLocalSystem(); x.SetDescription("Sample Topshelf Host"); x.SetDisplayName("Stuff"); x.SetServiceName("stuff"); }); 

TopShelf还负责服务安装,这可以节省大量的时间,并从您的解决scheme中删除样板代码。 要将.exe作为服务安装,只需在命令提示符下执行以下命令:

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

你不需要连接一个ServiceInstaller和所有的东西 – TopShelf这一切都为你。

所以这是完整的演练:

  1. 创build新的控制台应用程序项目(例如MyService)
  2. 添加两个库引用:System.ServiceProcess和System.Configuration.Install
  3. 添加下面打印的三个文件
  4. build立项目并运行“InstallUtil.exe c:\ path \ to \ MyService.exe”
  5. 现在你应该在服务列表上看到MyService(运行services.msc)

* InstallUtil.exe通常可以在这里find: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); } } } 

您可以使用

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

它会出现在服务列表中。 我不知道,但是这是否正常工作。 一个服务通常需要听几个事件。

有几个服务包装,虽然可以运行任何应用程序作为一个真正的服务。 对于Win2003资源工具包中的示例Microsofts SrvAny

我听到你想要一个程序集停止重复的代码,但是,这将是最简单的,减less代码的重复,并使以后更容易以其他方式重用你的代码,如果……你把它分解成3个程序集。

  1. 一个图书馆大会,所有的工作。 然后有两个非常非常苗条/简单的项目:
  2. 一个是命令行
  3. 一个是windows服务。

首先,我将控制台应用程序解决schemeembedded到Windows服务解决scheme中并引用它。

然后我使控制台应用程序类公开

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

然后我在控制台应用程序中创build两个函数

  /// <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服务本身,我实例化程序并调用在OnStart和OnStop中添加的启动和停止function。 见下文

 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服务混合

也许你应该定义你所需要的,据我所知,你不能以命令行的方式同时运行你的应用程序作为控制台或服务。 请记住,该服务已安装,您必须在服务pipe理器中启动它,您可以创build一个启动该服务的新应用程序或启动运行您的控制台应用程序的新进程。 但是,正如你写的

“保持控制台应用程序为一个项目”

有一次,我是在你的位置,把一个控制台应用程序变成一个服务。 首先你需要模板,以防你使用VS Express Edition。 这里有一个链接,你可以有你的第一步: C#Windows服务 ,这是对我非常有帮助。 然后使用该模板,将您的代码添加到服务的所需事件。

为了提高服务质量,还有一件事情可以做,但这不是快捷和/或简单,使用appdomains,并创buildDLL来加载/卸载。 在一个你可以启动一个新的进程与控制台的应用程序,而在另一个DLL,你可以把这个function服务必须做的。

祝你好运。

您需要将function分成一个或多个类,并通过两个存根之一启动。 控制台存根或服务存根。

显而易见,在运行Windows时,组成基础架构的无数服务不会(也不能直接)将控制台窗口呈现给用户。 该服务需要以非graphics方式与用户进行通信:通过SCM; 在事件日志中,某些日志文件等等。服务也需要通过SCM与Windows进行通讯,否则会closures。

拥有一些可以与服务进行通信的控制台应用显然是可以接受的,但是服务需要独立运行而不需要GUI交互。

控制台存根对于debugging服务行为非常有用,但不应该用于“生产”环境,毕竟这是一个创build服务的目的。

我还没有完全阅读,但这篇文章似乎朝着正确的方向前进。