如何更简洁、方便的注册 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 服务
基础教程推荐
猜你喜欢
- c#动态执行脚本的3种方式详解 2023-07-18
- C# .NET中Socket简单实用框架的使用教程 2022-11-11
- C#爬虫基础之HttpClient获取HTTP请求与响应 2023-06-09
- C#单线程和多线程端口扫描器详解 2023-06-27
- C#多态详解 2023-05-06
- c# – EF4.1 – Fluent API – SqlQuery – 调用sproc时的配置映射 – 数据读取器与指定的实体类型不兼容 2023-11-23
- 10分钟学会VS NuGet包私有化部署 2023-05-05
- C#使用Aspose.Cells创建和读取Excel文件 2023-01-06
- C#使用表达式树实现对象复制的示例代码 2023-05-12
- C# 实例解释面向对象编程中的单一功能原则(示例代码) 2023-05-17