C# .NET控制台应用程序作为Windows服务
我有控制台应用程序,希望将其作为Windows服务运行。VS2010具有允许附加控制台项目和生成Windows服务的项目模板。 我不想添加单独的服务项目,如果可能的话,将服务代码集成到控制台应用程序中,使控制台应用程序作为一个项目运行,可以作为控制台应用程序运行,或者作为windows服务运行(例如,使用开关从命令行运行) 也许有人会建议使用类库或代码片段,可以快速轻松地将c#控制台应用程序转换为服务 您可以使用C# .NET控制台应用程序作为Windows服务,c#,.net-4.0,windows-services,console-application,C#,.net 4.0,Windows Services,Console Application,我有控制台应用程序,希望将其作为Windows服务运行。VS2010具有允许附加控制台项目和生成Windows服务的项目模板。 我不想添加单独的服务项目,如果可能的话,将服务代码集成到控制台应用程序中,使控制台应用程序作为一个项目运行,可以作为控制台应用程序运行,或者作为windows服务运行(例如,使用开关从命令行运行) 也许有人会建议使用类库或代码片段,可以快速轻松地将c#控制台应用程序转换为服务 您可以使用 reg add HKEY_CURRENT_USER\Software\Micros
reg add HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run /v ServiceName /d "c:\path\to\service\file\exe"
它将出现在服务列表中。但我不知道这是否正确。一个服务通常需要监听多个事件
不过,有几种服务包装器可以将任何应用程序作为真正的服务运行。例如,Microsofts从也许你应该定义你需要什么,据我所知,你不能同时使用命令行作为控制台或服务运行你的应用程序。请记住,该服务已安装,您必须在Services Manager中启动它,您可以创建一个新的应用程序来启动该服务或启动运行控制台应用程序的新进程。但正如你所写 “将控制台应用程序保留为一个项目” 有一次,我处于您的位置,将控制台应用程序转变为服务。首先,您需要模板,以防使用VS Express Edition。这里有一个链接,你可以在这里看到你的第一步:,这对我很有帮助。然后使用该模板,将代码添加到服务的所需事件中 为了改进您的服务,您还可以做另一件事,但这并不快速和/或容易,那就是使用appdomains并创建DLL来加载/卸载。在其中一个应用程序中,您可以使用console应用程序启动一个新进程,在另一个dll中,您可以只放置服务必须执行的功能
祝您好运。您需要将功能划分为一个或多个类,并通过两个存根之一启动。控制台存根或服务存根 显而易见,在运行windows时,构成基础设施的无数服务不会(也不能直接)向用户提供控制台窗口。服务需要以非图形方式与用户通信:通过SCM;在事件日志中,指向某些日志文件等。该服务还需要通过SCM与windows通信,否则将被关闭 显然,可以接受一些控制台应用程序与服务进行通信,但服务需要独立运行,而不需要GUI交互 控制台存根对于调试服务行为非常有用,但不应在“productionized”环境中使用,毕竟这是创建服务的目的
我还没有完全阅读,但似乎方向不对。我听到你的观点是希望一个程序集停止重复代码,但是,如果。。。。。。您需要将其分解为3个程序集
我通常使用以下技术运行与控制台应用程序或服务相同的应用程序:
using System.ServiceProcess
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是一个Nuget软件包,旨在轻松创建可作为控制台应用程序或Windows服务运行的.NET Windows应用程序。您可以快速连接事件,如服务启动和停止事件,使用代码进行配置,例如设置其运行的帐户,配置对其他服务的依赖关系,以及配置其如何从错误中恢复
从包管理器控制台(Nuget):
安装组件Topshelf
请参阅以开始
例如:
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");
});
您不需要连接ServiceInstaller,所有这些—TopShelf都可以为您完成。首先,我将控制台应用程序解决方案嵌入到windows服务解决方案中并引用它 然后我将控制台应用程序类公开
/// <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
}
//
///用于作为服务启动
///
公开作废开始()
{
Main();
}
///
///用于停止服务
///
公共停车场()
{
if(Application.MessageLoop)
Application.Exit();//windows应用程序
其他的
Environment.Exit(1);//控制台应用程序
}
然后在windows服务本身中,我实例化该程序并调用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();
}
}
类WinService:ServiceBase
{
只读程序_应用程序=新程序();
///
///应用程序的主要入口点。
///
静态void Main()
{
ServiceBase[]servicesToRun={new WinService()};
运行(servicesToRun);
}
///
///启动工作,使您的服务能够完成其工作。
///
启动时受保护的覆盖无效(字符串[]args)
{
线程线程=新线程(()=>_application.Start());
thread.Start();
}
///
///停止这项服务。
///
受保护的覆盖void OnStop()
{
线程线程=新线程(()=>_application.Stop());
thread.Start();
}
}
此方法也可用于windows应用程序/windows服务的混合,下面是完整的演练:
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();
}
}
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));
}
}
}
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();
}
}
}
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);
}
}
}
public class Service : ServiceBase
{
protected override void OnStart(string[] args)
{
// Start logic here.
}
protected override void OnStop()
{
// Stop logic here.
}
static void Main(string[] args)
{
using (var service = new Service()) {
if (Environment.UserInteractive) {
service.Start();
Thread.Sleep(Timeout.Infinite);
} else
Run(service);
}
}
public void Start() => OnStart(null);
}
Install-Package Microsoft.Extensions.Hosting.WindowsServices -Version 3.1.0
Install-Package Microsoft.Extensions.Configuration.Abstractions -Version 3.1.0
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace ConsoleApp
{
class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).UseWindowsService().Build().Run();
}
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
}
}
using Microsoft.Extensions.Hosting;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp
{
public class Worker : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
//do some operation
}
public override Task StartAsync(CancellationToken cancellationToken)
{
return base.StartAsync(cancellationToken);
}
public override Task StopAsync(CancellationToken cancellationToken)
{
return base.StopAsync(cancellationToken);
}
}
}
sc.exe create DemoService binpath= "path/to/your/file.exe"