如何更简洁、方便的注册 windows 服务,并对服务的声明周期进行有效管理?C# Windows 服务程序,提供了一种很好的手段。可以通过写一个 C# Windows 服务代理程序,将其注册为 Windows 服务,然后在内部再调用其他程...
如何更简洁、方便的注册 windows 服务,并对服务的声明周期进行有效管理?C# Windows 服务程序,提供了一种很好的手段。
可以通过写一个 C# Windows 服务代理程序,将其注册为 Windows 服务,然后在内部再调用其他程序,比如 Java 程序。
使用 VisualStudio 创建 C# Windows 服务程序
详细步骤,网上有很多,也很简单。
Service1.cs
服务程序的主要逻辑:
- 服务启动后,读取服务程序当前目录下的 start.bat 文件内容,然后调用 Process 启动目标程序。
- 在新线程中,等待目标程序结束;
- 创建一个周期性的任务,往服务日志中写消息;
- 当目标程序退出时,使用本服务的 ServiceController 实例,将服务关闭。
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.IO;
namespace BTCI
{
public partial class Service1 : ServiceBase
{
System.Diagnostics.Process p;
System.Threading.Timer recordTimer;
Thread starter;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
IntialLogger(); // 启动程序后,启动监控日志
log(DateTime.Now.ToString() + " [info] start service");
starter = new Thread(startProcess);
starter.Start();
//startProcess();
return;
}
private void startProcess()
{
string cmd;
log(DateTime.Now.ToString() + " [info] start sub process");
log(DateTime.Now.ToString() + " [info] current directory = " + Directory.GetCurrentDirectory());
try
{
using (StreamReader sr = new StreamReader("start.bat"))
{
cmd = sr.ReadLine();
}
log(DateTime.Now.ToString() + " [info] start.bat content = " + cmd);
if (String.IsNullOrEmpty(cmd))
{
log(DateTime.Now.ToString() + " [error] cmd is null");
return;
}
p = new System.Diagnostics.Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false; //是否使用操作系统shell启动
p.StartInfo.RedirectStandardInput = true; //接受来自调用程序的输入信息
p.StartInfo.RedirectStandardOutput = true; //由调用程序获取输出信息
p.StartInfo.RedirectStandardError = true; //重定向标准错误输出
p.StartInfo.CreateNoWindow = true; //不显示程序窗口
log(DateTime.Now.ToString() + " [info] process started");
p.Start();//启动程序
//向cmd窗口发送输入信息
p.StandardInput.WriteLine(cmd + "&exit");
p.StandardInput.AutoFlush = true;
p.WaitForExit();//等待程序执行完退出进程
log(DateTime.Now.ToString() + " [info] process exit");
p.Close();
releaseTimer();
}
catch (Exception e)
{
// 向用户显示出错消息
log(DateTime.Now.ToString() + " [error] start sub process failed; "+e.Message);
return;
}
}
protected override void OnStop()
{
log(DateTime.Now.ToString() + " [info] stop service ");
releaseTimer();
}
private void IntialLogger()
{
TimerCallback timerCallback = new TimerCallback(CallbackTask);
AutoResetEvent autoEvent = new AutoResetEvent(false);
recordTimer = new System.Threading.Timer(timerCallback, autoEvent, 10000, 6000);
}
private void releaseTimer()
{
if (recordTimer != null)
{
log(string.Format(@"{0} [info] release timer", DateTime.Now));
recordTimer.Dispose();
}
log(string.Format(@"{0} [info] service exit", DateTime.Now));
ServiceController sc = new ServiceController("TargetServiceName");// 这里一定要与服务名称一致!不是显示名称!
if (sc.Status.Equals(ServiceControllerStatus.Running))
{
sc.Stop();
sc.Refresh();
}
}
private void CallbackTask(Object stateInfo)
{
//log(string.Format(@"{0} [info] service running", DateTime.Now));
if (starter.IsAlive)
{
log(string.Format(@"{0} [info] service running", DateTime.Now));
}
else
{
log(string.Format(@"{0} [error] thread is not alive", DateTime.Now));
releaseTimer();
}
}
private static void log(string content)
{
if (string.IsNullOrEmpty(content))
{
return;
}
try
{
string logFile = Path.Combine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase, string.Format("service.{0:yyyyMMdd}.log", DateTime.Now));
using (FileStream fileStream = new FileStream(logFile, FileMode.Append, FileAccess.Write))
{
using (StreamWriter streamWriter = new StreamWriter(fileStream))
{
streamWriter.WriteLine(content);
}
}
}
catch { }
}
}
}
沃梦达教程
本文标题为:C# Windows 服务
![](/xwassets/images/pre.png)
![](/xwassets/images/next.png)
猜你喜欢
- C#实现判断文件夹存在与否并创建文件夹的方法 2022-10-27
- C#获取DataTable对象状态DataRowState 2023-05-22
- C#使用TensorFlow.NET训练自己的数据集的方法 2023-02-09
- C#多线程之Semaphore用法详解 2022-11-10
- C#通过rabbitmq实现定时任务(延时队列) 2023-04-21
- .NET Core 使用Topshelf方式创建Windows服务 2023-09-27
- C#多线程系列之线程通知 2023-05-22
- C#数据类型实现背包、队列和栈 2023-05-31
- 浅谈Unity中的Shader 2023-04-22
- c#添加Newtonsoft.Json包的操作 2023-03-29