如何更简洁、方便的注册 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 { }
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。