C# 开发一个简单的 Window Service 入门

本贴最后更新于 2107 天前,其中的信息可能已经斗转星移

开始

创建项目

创建一个 Windows 服务的项目

9924aa85109d403a9bbf63f5607c3f21-QQ20180302143821.png

创建成功后的目录结构

b45de38afaa24a7cae9f6a09a3998219-QQ20180302144035.png

App.config 应用程序配置文件
Program.cs 程序入口文件
Service1.cs WindowService 主文件

准备代码

创建日志类

创建一个日志类 LogHeper.cs

class LogHelper
{
  public static void Info(string msg)
  {
	if (!Directory.Exists("C:\\DemoServiceLog"))
	  Directory.CreateDirectory("C:\\DemoServiceLog");
	string file = "C:\\DemoServiceLog\\" + DateTime.Now.ToString("yyyy-MM-dd") + ".log";
	if (!File.Exists(file))
	{
	  StreamWriter sw = File.AppendText(file);
	  sw.Close();
	}
	while (true)
	{
	  try
	  {
		StreamWriter sw = File.AppendText(file);
		sw.WriteLine(DateTime.Now.ToString("HH:mm:ss.s") + "  " + msg);
		sw.Close();
		break;
	  }
	  catch (Exception e)
	  {
		System.Threading.Thread.Sleep(50);
		continue;
	  }
	}
  }
}

调整 Service 类

在强迫症的驱使下将 Service1.cs 改名为 Service.cs

同时 Program.cs 类中也需要指定 Service.cs

static class Program
{
  /// <summary>
  /// 应用程序的主入口点。
  /// </summary>
  static void Main()
  {
	ServiceBase[] ServicesToRun;
	ServicesToRun = new ServiceBase[]
	{
	  new Service()
	};
	ServiceBase.Run(ServicesToRun);
  }
}

是的,它可以在 ServiceBase 里面指定多个服务。在这个 Demo 里面我们只运行一个。

编写服务程序的事件

右键 Service.cs 类查看代码

public partial class Service : ServiceBase
{
  public Service()
  {
	InitializeComponent();
  }
  protected override void OnStart(string[] args)
  {
	LogHelper.Info("Service is start...");
  }

  protected override void OnStop()
  {
	LogHelper.Info("Service is stop...");
  }
}

默认重写了两个事件 ,一个服务启动(OnStart)事件,一个服务停止事件(OnStart)

d66b558757174980942987d02eabb003-image.png

还支持 暂停,继续,电源关闭等事件

需要注意一点的是,在这些事件中的代码千万不能出现堵塞以及死循环的代码。否则会导致启动或停止失败。甚至卸载都会出现问题。

曾不小心在启动事件中,监听了一个端口,堵塞在那里,导致启动不成功。卸载过程中提示目标服务已被标记为删除,最后通过删除注册表信息才得以卸载。

服务的安装与卸载

服务的信息配置

目前一个简单的 WindowService 算是完成。在启动和关闭的时候将记录在日志当中。

那么怎么让他安装在用户的机器上呢?

其实也很简单,首先双击 Service.cs

在激活的标签页里面右键添加安装程序

项目目录里面会多出一个 ProjectInstaller.cs 项,双击后出现

da408e922b5f4aea9e15d6263ab017f2-image.png

选中 serviceProcessInstaller1 选择 AccountLocalSystem

2477c88926024799ac1a138d5ea2d4d6-image.png

选中 serviceInstaller1 后配置服务信息

e6a50049a5ce458b809623c5ef2b22d7-image.png

Description 服务描述
DisplayName 给用户的一个友好名称
ServiceName 服务的名称

服务安装与卸载批处理文件

创建一个 install.bat 文件

@ECHO OFF
echo 准备安装服务
pause
echo 安装服务...
echo ---------------------------------------------------
%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe %~dp0\DemoService.exe
net start DemoService
sc config DemoService start=auto
echo ---------------------------------------------------
echo 安装服务成功!
pause

调用.NET Framework 的 installutil.exe 程序进行安装服务
安装成功后通过 net start DemoService 启动服务
sc config Demoservice start=auto 配置服务的启动类型为自动,相当于开机启动

创建一个 uninstall.bat 文件

@ECHO OFF
echo 准备卸载服务
pause
echo 卸载服务...
echo ---------------------------------------------------
%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe %~dp0\DemoService.exe -u
sc delete DemoService
Net Stop DemoService
echo ---------------------------------------------------
echo 卸载服务成功!
pause

将这两个文件与项目生成出来的 DemoService.exe 放在同级目录下,右键已管理员方式运行即可完成安装与卸载。

在 C 盘产生的日志文件中也记录了我们在代码中输出的信息

Win+R 输入 service.msc 即可找到安装成功的服务

bdcef4d38fd243dba5ad4479379113c9-image.png

其中 Window Service Demo 只是一个友好的名称而并非服务真正的名称

真正的名称在我们刚刚在 serviceInstaller1 配置的 ServiceName

结语

一个简单的 Window Service 就已经完成了。虽然他并没有完成什么特别令人有成就感的行为,也没有做出什么惊天地泣鬼神的操作。

但这只是一个引子。一个 Window Service 入门的引子。通过 Window Service 我们可以做很多有意思的事情。

我主要是做 JAVA WEB 开发的,大家都知道浏览器最初设计为了安全考虑,浏览器上所执行的脚本是不允许和用户的机器交互的,也仅仅是缓存一些东西而已,对用户威胁不大。

举一个简单的例子,浏览器上传文件,可以说是都是用户自主触发的,都是经过用户的同意的。正常情况下是不可能自动将用户的文件上传上去。

最早浏览器与客户端交互的一个中间件叫做 OCX 控件或 ActiveX 控件,或许还有其他的控件。但是他们只能在那个令人诟病的 IE 浏览器上使用。

后面我将会写一篇关于通过 Window 服务让浏览器与客户端交互的一个案例。满足一些特殊需求。

  • C#
    29 引用 • 34 回帖 • 5 关注
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    222 引用 • 473 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • salamander

    以前弄的 wnmp
    控制 MySQL 也是用 windows Service 做的