最近写了个控制台应用程序,功能是监控对应文件夹内DICOM文件,若有文件则读取进行处理,处理后将文件移除。其中没有任何手动输入,程序又需要一直运行,但是控制台应用容易被随手关掉,所以决定做成服务。话不多说,从创建开始记录~
一、创建编写Windows服务
1.创建项目
选择创建Windows服务,更改项目名称和位置,如下图
2.添加安装程序(添加后才能将你的Windows服务安装,不然无法启动)
成功创建后,出现如下界面
在空白处右击,出现菜单单击添加安装程序
出现如下画面
分别右击两个组件更改其属性
3.编写服务代码
构造函数里面写初始化代码,OnStart里面是服务器开启时运行的函数,OnStop里面是服务器停止时运行的函数,
注意:不要在这两个函数里面写死循环,不然服务无法运行,因为运行完函数才会服务才会开启,不然就会处于"启动"的状态,既不是已启动也不是没启动,无法停止也无法启动,只能直接卸载掉。
我写了个测试方法,将信息写入名为当前日期的txt文件中,代码如下:
public Service1()
{
InitializeComponent();
creatf("Initialization");
}
protected override void OnStart(string[] args)
{
creatf("OnStart");
}
protected override void OnStop()
{
creatf("OnStop");
}
public void creatf(string str)//操作日志
{
//获取当前日期
string s = DateTime.Now.ToString("yyyy-MM-dd");
string time = DateTime.Now.ToLongTimeString().ToString();
string path = Directory.GetCurrentDirectory()+"\\log";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
path = path +"\\"+ s + ".txt";
if (!File.Exists(path))
{
FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
long fl = fs.Length;
fs.Seek(fl, SeekOrigin.End);
sw.WriteLine("[" + DateTime.Now.ToString("F") + "]:" + str + "\n");//开始写入值
sw.Close();
fs.Close();
}
else
{
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Write);
StreamWriter sw = new StreamWriter(fs);
long fl = fs.Length;
fs.Seek(fl, SeekOrigin.Begin);
sw.WriteLine("[" + DateTime.Now.ToString("F") + "]:" + str + "\n");//开始写入值
sw.Close();
fs.Close();
}
}
其中Directory.GetCurrentDirectory()是获取项目的当前目录,但是注册成服务后,这个目录就变成了C:\Windows\System32(或C:\Windows\SysWOW64),这样没有达到想要的效果。
所有的Windows服务都在注册表中有对应记录,其中imagepath就是你的服务.exe安装的目录,对此可以添加一个获取服务安装路径的函数:
///
/// 获取服务安装路径
///
///
///
public static string GetWindowsServiceInstallPath(string ServiceName)
{
string key = @"SYSTEM\CurrentControlSet\Services\" + ServiceName;
string path = Registry.LocalMachine.OpenSubKey(key).GetValue("ImagePath").ToString();
//替换掉双引号
path = path.Replace("\"", string.Empty);
FileInfo fi = new FileInfo(path);
return fi.Directory.ToString();
}
由此可将creatf函数中的Directory.GetCurrentDirectory()改为GetWindowsServiceInstallPath("你的服务名称")
生成项目无错ok
二、安装与卸载服务
生成的exe是不能直接打开的,需要安装,安装有多种方法,这里介绍通过批处理文件安装。
1.安装
新建txt文件,更改后缀为.bat,用记事本打开编辑如下。
@echo.请稍等,服务启动......
@echo off
@sc create testName binPath= "%~dp0%WindowsService2.exe"
@net start testName
@sc config testName start= AUTO
@sc description testName 这是一个测试服务
@echo off
@echo.启动完毕!
@pause
testName是服务的名称,
binPath是生成的exe文件,%~dp0%是批处理文件所在目录,也可改成绝对路径
description是显示的服务描述
成功效果如下:
此时服务已经启动,运行了之前写的代码,在生成log目录和名为当前日期的文件
2.卸载
新建txt文件,更改后缀为.bat,用记事本打开编辑如下。
@echo.服务卸载......
@echo off
@sc stop testName
@sc delete testName
@sc stop testName
@echo off
@echo.卸载完毕!
@pause
成功效果如下:
至此整个流程都完成了,有疑问或错误请指出,谢谢
新更新一直安装服务的bat,一句ok
安装:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe AutoInspectionSys.exe
卸载:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe /u AutoInspectionSys.exe