一、简介
程序创建在 Windows 会话中,可长时间运行的可执行应用程序。这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面。这些功能使服务非常适合在服务器上使用,需要使用时不会影响在同一台计算机上工作的其他用户的功能。还可以在不同于登录用户的特定用户帐户或默认计算机帐户的安全上下文中运行服务。说白了就是在windows后台运行,计算机自己跑的后台程序。
二、demo建立
1)新建一个Windows服务WindowsServiceDemo如下图,win10,vs2013.
2)更改项目启动项。Program.cs中修改 new ServiceBase 构造函数,首页构造出 MainService.cs 为首页。
static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> static void Main() { ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new MainService() }; ServiceBase.Run(ServicesToRun); } }
3)创建2)中的首页MainService,并在该类构造函数初化.net(InitializeComponent()),初始化Windows服务程序(InitService())。windows服务初始化时候会调用StartThread()开始任务,StartThread()调用MessageAdd日志记录,MessageAdd调用FileClass文件助手类,fileClass中会有具体的文件夹建立,文件的增删改,以及具体文件的增加日期功能。
OnStart :服务启动的时候执行,
OnStop:服务停止的时候执行
MainService.cs如下
using System; using System.ServiceProcess; using System.Timers; namespace WindowsServiceDemo { partial class MainService : ServiceBase { private static object syncRoot = new Object();//同步锁 public static string serviceName = "Windows服务程序"; FileClass fileClass = new FileClass(); System.Timers.Timer tim; private string logPath = System.Windows.Forms.Application.StartupPath + @"Log";//日志文件路径 #region 公共设置 public MainService() { //.net初始化 InitializeComponent(); InitService(); } #endregion protected override void OnStart(string[] args) { try { this.tim.Enabled = true; this.tim.Start(); } catch (Exception ex) { MessageAdd("OnStart错误:" + ex.Message); } MessageAdd(serviceName + "已成功启动!"); } protected override void OnStop() { try { this.tim.Stop(); } catch (Exception ex) { MessageAdd("OnStop错误:" + ex.Message); } MessageAdd(serviceName + "已停止!"); } protected override void OnContinue() { this.tim.Start(); base.OnContinue(); } protected override void OnPause() { this.tim.Stop(); base.OnPause(); } /// <summary> /// 初始化服务参数 /// </summary> private void InitService() { CanShutdown = true; CanStop = true; CanPauseAndContinue = true; ServiceName = MainService.serviceName; AutoLog = false;//为了使用自定义日志,必须将 AutoLog 设置为 false tim = new System.Timers.Timer(); tim.Elapsed += new ElapsedEventHandler(tim_Elapsed); tim.Interval = 5000; tim.AutoReset = true; } private void tim_Elapsed(object sender, EventArgs e) { StartThread(); } /// <summary> /// 开始任务 /// </summary> private void StartThread() { MessageAdd(serviceName + " " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); } /// <summary> /// 日志记录 /// </summary> /// <param name="serviceName">内容</param> public void MessageAdd(string str) { try { fileClass.WriteLogFile(logPath, str);//写入记录日志 } catch(Exception e) { return; } } } }
4)MainService.cs中调用了类fileClass.cs来对文件的具体操作
FileClass.cs如下
using System; using System.IO; namespace WindowsServiceDemo { class FileClass { //说白了就是增加文件夹,增删改文件,增加文件内容 //创建文件夹 public bool CreateFolder(string path) { try { if (Directory.Exists(path)) { return true; } if (!Directory.Exists(path.Substring(0, path.LastIndexOf("\")))) { //若路径中无“”则表示路径错误 return false; } else { //创建文件 DirectoryInfo dirInfo = Directory.CreateDirectory(path); return true; } } catch (Exception) { return false; } } //创建文件 public void CreateFile(string path) { try { if (CreateFolder(path.Substring(0, path.LastIndexOf("\")))) { if (!File.Exists(path)) { FileStream fs = File.Create(path); fs.Close(); } } else { return; } } catch (Exception e) { return ; } } //删除文件 public void DeleceFile(string path) { try { if (!File.Exists(path)) { return; } else { File.Delete(path); } } catch (Exception ex) { return; } } //写文件 public void WriteFile(string path, string content) { try { if (!File.Exists(path)) { CreateFile(path); } FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write); StreamWriter sw = new StreamWriter(fs); sw.WriteLine(content); sw.Close(); } catch (Exception exception) { return; } } /// <summary> /// 将即时日志保存入日志文件 /// </summary> /// <param name="directoryPath"></param> /// <param name="content"></param> public void WriteLogFile(string directoryPath, string content) { if (!Directory.Exists(directoryPath)) { CreateFolder(directoryPath); } try { //写入新的文件 string filePath = directoryPath + "\" + DateTime.Now.ToString("yyyyMMdd" + ".log"); FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write); StreamWriter sw = new StreamWriter(fs); sw.WriteLine(content); sw.Close(); fs.Close();; } catch (Exception) { return; } } } }
在这个类的编写中会遇到缺少引用的编译错误,在引用中添加System.Windows.Forms该引用在框架中查找,而并非在扩展中
5)完成上述步骤以后项目就可以编译通过了。然后进行项目部署。
6)左键双击MainService.cs也就是上边说的首页,然后在空白的地方右键
点击“添加安装程序”。自动生成ProjectInstaller.cs。进入ProjectInstaller.cs按下图编辑两个插件的属性
保存更改。
7)然后以管理员进入cmd 输入: C:WindowsMicrosoft.NETFrameworkv4.0.30319InstallUtil.exe "D:visual studio 2013ProjectsWindowsServiceDemoWindowsServiceDemoinDebugWindowsServiceDemo.exe" 回车,安装成功
8)输入: C:WindowsMicrosoft.NETFrameworkv4.0.30319InstallUtil.exe /u "D:visual studio 2013ProjectsWindowsServiceDemoWindowsServiceDemoinDebugWindowsServiceDemo.exe"
C:WINDOWSsystem32>C:WindowsMicrosoft.NETFrameworkv4.0.30319InstallUtil.exe 是在程序部署时候需要依赖一个.net程序集,我是默认安装在c盘下,找到该安装程序 工具。
D:visual studio 2013ProjectsWindowsServiceDemoWindowsServiceDemoinDebugWindowsServiceDemo.exe 是我的项目所在位置进入bin下..
如果不是管理员登入cmd则会报错如下windows服务没有RunInstallerAttribute.Yes的公共安装程序
10)cmd services.msc 进入win服务,开启“Windows服务Demo”服务
去D:visual studio 2013ProjectsWindowsServiceDemoWindowsServiceDemoinDebugLog下找日志文件。打开以后是这个样子的,程序正确运行
11)启动调试功能
打开服务,管理员运行vs进入 “工具” > “添加到附加进程”,选择项目进程,设置断点可以调试。
三、总结及注意事项
整个项目文件,Service1.cs是废弃的首页,下图错误,从新配图
服务如上。
displayName是在服务中显示的名字,进程是那个安装包儿的名字,也就是.exe文件
项目源码:http://pan.baidu.com/s/1ge7bWIJ