用.Net开发Windows服务十分简单,通常我们将程序做成服务运行,其实就是为了让系统不停的去做某一件事或几件事。所以我们首先要考虑清楚,让服务做什么“事”?在思考这个“事”的时候,其实也是在将复杂的需求简单化为一个或几个过程。这“事”定义出来后,服务开发、调用、安装布属就简单了。
.Net的服务提供了OnStart、OnStop方法。简单说OnStart就是服务启动时的一个事件,OnStop就是停止服务的事件。我们只需要在服务的启动事件中,创建一个线程让它不断的去做“事”,在停止事件中将线程终止掉,就是这么简单。
下面我用一个简单的实例,来讲解服务从“开发”-》“测试”-》“布属”-》“更新”的方法
从最简单的开始,我们先定义前面说到的这个“事”:就让服务每隔几分钟打印一段“Hello World!”吧。
步骤一:定义好“事”
我们先新建一个类库,这里我取名叫“TestService”,新建一个“CenterControl”类。在该类中定义“启动”、“停止”方法(这两个方法是给服务调的)。在类中实现我们的逻辑,详见附代码。
public class CenterControl
{
private Thread thread = null;
private bool isBreak = false;
/// <summary>
/// 启动
/// </summary>
public void Start()
{
isBreak = false;
thread = new Thread(new ThreadStart(threadProc));
thread.Name = "线程名...";
thread.IsBackground = true;
thread.Start();
}
/// <summary>
/// 停止
/// </summary>
public void Stop()
{
try
{
isBreak = true;
if (null != thread && !thread.Join(5000))
{
thread.Abort();
}
}
catch (Exception ex)
{
Debug.WriteLine(String.Format("Error:{0}", ex.Message));
}
}
/// <summary>
/// 线程体
/// </summary>
private void threadProc()
{
try
{
while (!isBreak)
{
Debug.WriteLine("Hello World!");
Thread.Sleep(60 * 1000);
}
}
catch (ThreadAbortException tae)
{
Thread.ResetAbort();
Debug.WriteLine(String.Format("Error:{0}", tae.Message));
}
catch (Exception ex)
{
Debug.WriteLine(String.Format("Error:{0}", ex.Message));
}
}
}
在这里我说明一下,为什么我要先建一个类库,而不直接建服务,然后将这些逻辑直接写在服务提供的OnStart、和OnStop中。原因很多,主要原因是为了方便调试与更新。如果直接建立服务,调试时很不方便,也很难调试,好像是要附加到进程啥的,我没研究过。我在这里主要介绍我自已的方法。我们将要做的“事”放到了一个类库中,这个类库向服务提供了Start、Stop两个方法。意味着我们只需要写一个简单的应用程序调用Start、Stop两个方法。即可摸拟出服务调用。
步骤二:测试
我们新建一个应用程序,我这里是命名为“TestServiceApp”,引用步骤一创建的类库。在窗体上放置两个“Button”,一个为OnStart、一个为OnStop。并实现它们的单击事件。
using TestService;
namespace TestServerApp
{
public partial class Form1 : Form
{
CenterControl cc = new CenterControl();
public Form1()
{
InitializeComponent();
}
private void button_OnStart_Click(object sender, EventArgs e)
{
cc.Start();
}
private void button_OnStop_Click(object sender, EventArgs e)
{
cc.Stop();
}
}
}
将测试应用程序设为启动项目,我们就可以通过设置断点,来调试我们的服务。通过DebugView工具查看“Debug.WriteLine”的信息。来调试程序,在这里我也重点推荐一下DebugView工具。程序调试起来非常方便,特别是用于调多线程程序。下图是示例打印出来的消息。
步骤三:将类库装载到服务
新建Windows服务项目,我这里是命名为“TestWindowsService”。将步骤一创建的类库引用。并在服务的OnStart、OnStop事件中分别调用类库的Start、Stop方法(与测试应用程序调用相同)。
using TestService;
namespace TestWindowsService
{
public partial class Service1 : ServiceBase
{
private CenterControl cc = new CenterControl();
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
cc.Start();
}
protected override void OnStop()
{
cc.Stop();
}
}
}
程序实现好了,还需要添加一个服务安装类。选中“Service1 ”,右键-》打开它的属性面板,在较下端有一个“添加安装程序”。点击,将自动实现一个安装类。如下图:
在安装类中,有两个组件,服务安装的一些配置信息可通过这两个组件来配置。如:授权用户(ProjectInstaller.Account),服务名(ProjectInstaller.ServiceName),服务显示名(ProjectInstaller.DisplayName),启动方式(ProjectInstaller.StartType),描述(ProjectInstaller.Description)等。
步骤四:配置,并打包安装程序
新建安装程序项目,我这里命名为“TestServiceSetup”。打开安装项目的“应用程序文件夹”,右键“添加”-》“项目输出”。选择服务项目,即前面步骤三创建的“TestWindowsService”项目。以上是一般程序打包的操作,但是,Windows服务不一样的是,还需要进行后面的操作(具体我也还没搞清楚,感觉还是多余的操作,有知情的还望告知)。右键“TestServiceSetup”项目-》“视图”-》“自定义操作”,分别在“安装”、“提交”、“回滚”、“卸载”,添加自定义操作,出现对话框,选中“应用程序文件夹”中“主输出来自TestWindowsService(活动)”。
步骤五:更新
待续。。。