再谈Windows Service - 一个简单的自我例子和部署
我们的服务需要做两件自动的事情,一个是往表格中定时插入数据,另一个就是
往文件中定时插入内容
因此,我们需要做一个工作类,这个类可以是一个抽象类,如下:
TaskWorker
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
namespace WinConsoleService
{
public abstract class TaskWorker
{
private static readonly ILog logger = LogManager.GetLogger(typeof(TestTaskWorker));
public bool Pause { get; set; }
public bool Stop { get; set; }
public abstract void Run();
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
namespace WinConsoleService
{
public abstract class TaskWorker
{
private static readonly ILog logger = LogManager.GetLogger(typeof(TestTaskWorker));
public bool Pause { get; set; }
public bool Stop { get; set; }
public abstract void Run();
}
}
我们实际的工作任务是需要继承该抽象类的两个实体类,如下:
DbTaskWorker
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using WinConsoleService.DAL;
using System.Configuration;
using System.Diagnostics;
using log4net;
namespace WinConsoleService
{
public class DbTaskWorker: TaskWorker
{
//private static readonly ILog logger = LogManager.GetLogger(typeof(TestTaskWorker));
public bool Pause { get; set; }
public bool Stop { get; set; }
public override void Run()
{
//logger.Info("Test Task Work Started ...");
while (!Stop)
{
if (Pause)
continue;
Do();
Thread.Sleep(int.Parse(ConfigurationManager.AppSettings["WakeupInterval"]));
}
}
private void Do()
{
SqlDbUtil db = new SqlDbUtil();
string sql = @"insert into Test2
values('1', '2' , '3')";
int ret = db.ExecuteSQL(sql);
if (ret == -1)
FileUtil.WriteLog("Exception: database insert error!");
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using WinConsoleService.DAL;
using System.Configuration;
using System.Diagnostics;
using log4net;
namespace WinConsoleService
{
public class DbTaskWorker: TaskWorker
{
//private static readonly ILog logger = LogManager.GetLogger(typeof(TestTaskWorker));
public bool Pause { get; set; }
public bool Stop { get; set; }
public override void Run()
{
//logger.Info("Test Task Work Started ...");
while (!Stop)
{
if (Pause)
continue;
Do();
Thread.Sleep(int.Parse(ConfigurationManager.AppSettings["WakeupInterval"]));
}
}
private void Do()
{
SqlDbUtil db = new SqlDbUtil();
string sql = @"insert into Test2
values('1', '2' , '3')";
int ret = db.ExecuteSQL(sql);
if (ret == -1)
FileUtil.WriteLog("Exception: database insert error!");
}
}
}
FileTaskWorker
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Diagnostics;
using System.Configuration;
using log4net;
namespace WinConsoleService
{
public class FileTaskWorker : TaskWorker
{
private static readonly ILog logger = LogManager.GetLogger(typeof(FileTaskWorker));
public override void Run()
{
while (!Stop)
{
if (Pause)
continue;
Do();
Thread.Sleep(int.Parse(ConfigurationManager.AppSettings["WakeupInterval"]));
}
}
private void Do()
{
FileStream fs = new FileStream("E:\\PerformanceLog_" + DateTime.Now.ToString("yyyyMMdd") + ".log", FileMode.Append);
StreamWriter streamWriter = new StreamWriter(fs);
streamWriter.BaseStream.Seek(0, SeekOrigin.End);
streamWriter.WriteLine(DateTime.Now);
streamWriter.Flush();
streamWriter.Close();
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Diagnostics;
using System.Configuration;
using log4net;
namespace WinConsoleService
{
public class FileTaskWorker : TaskWorker
{
private static readonly ILog logger = LogManager.GetLogger(typeof(FileTaskWorker));
public override void Run()
{
while (!Stop)
{
if (Pause)
continue;
Do();
Thread.Sleep(int.Parse(ConfigurationManager.AppSettings["WakeupInterval"]));
}
}
private void Do()
{
FileStream fs = new FileStream("E:\\PerformanceLog_" + DateTime.Now.ToString("yyyyMMdd") + ".log", FileMode.Append);
StreamWriter streamWriter = new StreamWriter(fs);
streamWriter.BaseStream.Seek(0, SeekOrigin.End);
streamWriter.WriteLine(DateTime.Now);
streamWriter.Flush();
streamWriter.Close();
}
}
}
由于Windows Service调试起来比较困难,因此我做了一个文件日志,本来
考虑用log4net,但是log4net经常抽疯,所以还是自己做一个吧
FileUtil
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace WinConsoleService
{
public class FileUtil
{
public static void WriteLog(string ex)
{
/*
FileStream fs = new FileStream("C:\\test.log", FileMode.Append);
StreamWriter streamWriter = new StreamWriter(fs);
streamWriter.BaseStream.Seek(0, SeekOrigin.End);
streamWriter.WriteLine(ex);
streamWriter.Flush();
*/
StreamWriter sw = File.AppendText("C:\\test.log");
sw.WriteLine(ex);
sw.Close();
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace WinConsoleService
{
public class FileUtil
{
public static void WriteLog(string ex)
{
/*
FileStream fs = new FileStream("C:\\test.log", FileMode.Append);
StreamWriter streamWriter = new StreamWriter(fs);
streamWriter.BaseStream.Seek(0, SeekOrigin.End);
streamWriter.WriteLine(ex);
streamWriter.Flush();
*/
StreamWriter sw = File.AppendText("C:\\test.log");
sw.WriteLine(ex);
sw.Close();
}
}
}
服务主体代码如下:
Service1.cs
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.IO;
using System.Threading;
using log4net;
namespace WinConsoleService
{
public partial class Service1 : ServiceBase
{
private TaskWorker worker;
ILog logger = LogManager.GetLogger(typeof(Service1));
public Service1()
{
FileUtil.WriteLog("Windows Service Start");
InitializeComponent();
this.worker = new FileTaskWorker();
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
try
{
Exception ex = e.ExceptionObject as Exception;
FileUtil.WriteLog("来自Service1的全局异常, " + ex.Message + "详细信息如下:"
+ Environment.NewLine + "[InnerException]" + ex.InnerException
+ Environment.NewLine + "[Source]" + ex.Source
+ Environment.NewLine + "[TargetSite]" + ex.TargetSite
+ Environment.NewLine + "[StackTrace]" + ex.StackTrace);
}
catch { }
}
protected override void OnStart(string[] args)
{
FileUtil.WriteLog("OnStart");
Thread t = new Thread(new ThreadStart(this.worker.Run));
t.Start();
}
protected override void OnStop()
{
FileUtil.WriteLog("OnStop");
this.worker.Stop = true;
this.worker.Pause = true;
}
protected override void OnPause()
{
FileUtil.WriteLog("OnPause");
this.worker.Pause = true;
}
protected override void OnContinue()
{
FileUtil.WriteLog("OnContinue");
this.worker.Pause = false;
}
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.IO;
using System.Threading;
using log4net;
namespace WinConsoleService
{
public partial class Service1 : ServiceBase
{
private TaskWorker worker;
ILog logger = LogManager.GetLogger(typeof(Service1));
public Service1()
{
FileUtil.WriteLog("Windows Service Start");
InitializeComponent();
this.worker = new FileTaskWorker();
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
}
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
try
{
Exception ex = e.ExceptionObject as Exception;
FileUtil.WriteLog("来自Service1的全局异常, " + ex.Message + "详细信息如下:"
+ Environment.NewLine + "[InnerException]" + ex.InnerException
+ Environment.NewLine + "[Source]" + ex.Source
+ Environment.NewLine + "[TargetSite]" + ex.TargetSite
+ Environment.NewLine + "[StackTrace]" + ex.StackTrace);
}
catch { }
}
protected override void OnStart(string[] args)
{
FileUtil.WriteLog("OnStart");
Thread t = new Thread(new ThreadStart(this.worker.Run));
t.Start();
}
protected override void OnStop()
{
FileUtil.WriteLog("OnStop");
this.worker.Stop = true;
this.worker.Pause = true;
}
protected override void OnPause()
{
FileUtil.WriteLog("OnPause");
this.worker.Pause = true;
}
protected override void OnContinue()
{
FileUtil.WriteLog("OnContinue");
this.worker.Pause = false;
}
}
}
控制台入口
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using log4net.Config;
namespace WinConsoleService
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
static void Main()
{
XmlConfigurator.Configure();
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using log4net.Config;
namespace WinConsoleService
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
static void Main()
{
XmlConfigurator.Configure();
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
}
最后,再次谈一下部署
首先,如果你用的是.NET4.0, 需要找到该目录:
C:\Windows\Microsoft.NET\Framework\v4.0.30319
然后,记住一定要把该路径添加到环境变量的path路径
如果是windows7的用户, 请记住一定要在管理员情况下运行Visual Studio Command Prompt
然后,把你Debug目录下的文件统统拷贝到记得服务目录,运行该命令
cd 服务目录
InstallUtil WinConsoleService.exe
这样,服务就部署完成了,以后重新修改服务,只要停止服务,覆盖原来的文件就好了
技术改变世界