WindowsService服务的C#实现

WindowsService(简称服务,下同)是目前做客户端软件后台运行功能的非常好的选择,本文基本解决了服务的创建和编写,代码控制服务的安装、卸载、启动、停止等,为服务传递参数,其他注意事项等

1、服务的创建和编写:

①在Add Project选择Windows Service创建项目,同时添加一个Windows Service类,在这里以IFUploaderService.cs为例

②在设计器中右键选择Add Installer,如图

③在生成的ProjectInstaller的设计器中设置

serviceProcessInstaller控件的属性 Account:LocalSystem (这样不论是以哪个用户登录的系统,服务总会启动)

serviceInstaller控件的属性 DisplayName:在系统服务管理界面显示的服务名称,根据你的程序命名,如图

        Description:在系统服务管理界面显示的服务描述,根据你的程序填写

        ServiceName:服务的真实名称,在系统中应该是唯一的,这也是接下来用程序控制服务的关键

        StartType:服务的启动类型,有自动、手动、和禁用

④打开IFUploaderService.cs,代码中的OnStart和OnStop事件将在服务开启和结束时执行

为了实现定时执行的功能,你可以在OnStart中添加一个Timer,比如我要在每天8点执行自动上传功能,代码如下

 1 protected override void OnStart(string[] args)
 2 {
 3     // TODO: Add code here to start your service.
 4     if (args.Length > 0)
 5     {
 6         //服务的工作路径转移到主程序所在目录
 7         System.Environment.CurrentDirectory = args[0];
 8         //记录服务开启的时间
 9         serviceStartTime = DateTime.Now;
10         //开启计时器
11         System.Timers.Timer t = new System.Timers.Timer();
12         t.Interval = 1000;
13         t.Elapsed += new System.Timers.ElapsedEventHandler(CheckUploadStatus);
14         t.AutoReset = true;
15         t.Enabled = true;
16         LogHelper.WriteLog("Service start");
17     }
18 }
19
20 protected override void OnStop()
21 {
22     // TODO: Add code here to perform any tear-down necessary to stop your service.
23     LogHelper.WriteLog("Service stop");
24 }
25
26 private void CheckUploadStatus(object sender, System.Timers.ElapsedEventArgs e)
27 {
28     if (DateTime.Now.ToString("HH:mm:ss") == "08:00:00")
29     {
30         UploadBegin();
31     }
32 }

IFUploaderService.cs

⑤Build项目,注意服务项目不能直接执行,接下来手动安装服务:

复制Build生成的exe文件的完整路径

打开Visual Studio Command Prompt(VS命令提示符),执行installutil Build后的exe文件路径,比如

installutil D:\EGFIS_IF\Eland.GEPS.POSIF.WinService\bin\Debug\Eland.GEPS.POSIF.WinService.exe

同理,卸载服务的命令是installutil /u Build后的exe文件路径

⑥调试时只需要在VS中附加项目生成的服务exe的进程即可

2、代码控制服务的安装、卸载、开启、关闭等

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Text;
  4 using System.ServiceProcess;
  5 using System.Configuration.Install;
  6 using System.Collections;
  7 using Microsoft.Win32;
  8
  9 namespace Eland.GEPS.POSIF.UI.Common
 10 {
 11     public static class ServiceHelper
 12     {
 13         #region 安装服务
 14         /// <summary>
 15         /// 安装服务
 16         /// </summary>
 17         /// <param name="filePath">服务名</param>
 18         /// <param name="nameService">程序文件路径(不带.exe)</param>
 19         /// <returns></returns>
 20         public static bool InstallService(string filePath, string nameService)
 21         {
 22             bool flag = true;
 23             if (!IsServiceExisted(nameService))
 24             {
 25                 try
 26                 {
 27                     string serviceFileName = filePath + ".exe";
 28                     InstallServiceExec(serviceFileName);
 29                 }
 30                 catch
 31                 {
 32                     flag = false;
 33                 }
 34             }
 35             return flag;
 36         }
 37         #endregion
 38
 39         #region 卸载服务
 40         /// <summary>
 41         /// 卸载服务
 42         /// </summary>
 43         /// <param name="filePath">服务名</param>
 44         /// <param name="nameService">程序文件路径(不带.exe)</param>
 45         /// <returns></returns>
 46         public static bool UninstallService(string filePath, string nameService)
 47         {
 48             bool flag = true;
 49             if (IsServiceExisted(nameService))
 50             {
 51                 try
 52                 {
 53                     string serviceFileName = filePath + ".exe";
 54                     UnInstallServiceExec(serviceFileName);
 55                 }
 56                 catch
 57                 {
 58                     flag = false;
 59                 }
 60             }
 61             return flag;
 62         }
 63         #endregion
 64
 65         #region 检查服务的存在性
 66         /// <summary>
 67         /// 检查服务的存在性
 68         /// </summary>
 69         /// <param name="nameService">服务名</param>
 70         /// <returns>存在返回 true,否则返回 false</returns>
 71         public static bool IsServiceExisted(string nameService)
 72         {
 73             ServiceController[] services = ServiceController.GetServices();
 74             foreach (ServiceController s in services)
 75             {
 76                 if (s.ServiceName.ToLower() == nameService.ToLower())
 77                 {
 78                     return true;
 79                 }
 80             }
 81             return false;
 82         }
 83         #endregion
 84
 85         #region 安装Windows服务
 86         /// <summary>
 87         /// 安装Windows服务
 88         /// </summary>
 89         /// <param name="filePath">程序文件路径</param>
 90         public static void InstallServiceExec(string filePath)
 91         {
 92             try
 93             {
 94                 string[] cmdline = { };
 95                 TransactedInstaller transactedInstaller = new TransactedInstaller();
 96                 AssemblyInstaller assemblyInstaller = new AssemblyInstaller(filePath, cmdline);
 97                 transactedInstaller.Installers.Add(assemblyInstaller);
 98                 transactedInstaller.Install(new System.Collections.Hashtable());
 99             }
100             catch (Exception)
101             {
102                 throw;
103             }
104         }
105         #endregion
106
107         #region 卸载Windows服务
108         /// <summary>
109         /// 卸载Windows服务
110         /// </summary>
111         /// <param name="filePath">程序文件路径</param>
112         public static void UnInstallServiceExec(string filePath)
113         {
114             try
115             {
116                 string[] cmdline = { };
117                 TransactedInstaller transactedInstaller = new TransactedInstaller();
118                 AssemblyInstaller assemblyInstaller = new AssemblyInstaller(filePath, cmdline);
119                 transactedInstaller.Installers.Add(assemblyInstaller);
120                 transactedInstaller.Uninstall(null);
121             }
122             catch (Exception)
123             {
124                 throw;
125             }
126         }
127         #endregion
128
129         #region 判断window服务是否启动
130         /// <summary>
131         /// 判断window服务是否启动
132         /// </summary>
133         /// <param name="serviceName">服务名</param>
134         /// <returns></returns>
135         public static bool IsServiceStart(string serviceName)
136         {
137             ServiceController sc = new ServiceController(serviceName);
138             bool startStatus = false;
139             try
140             {
141                 if (!sc.Status.Equals(ServiceControllerStatus.Stopped))
142                 {
143                     startStatus = true;
144                 }
145                 return startStatus;
146             }
147             catch (Exception)
148             {
149                 throw;
150             }
151         }
152         #endregion
153
154         #region 修改服务的启动项
155         /// <summary>
156         /// 修改服务的启动项
157         /// </summary>
158         /// <param name="startType">2为自动,3为手动</param>
159         /// <param name="serviceName">服务名</param>
160         /// <returns></returns>
161         public static void ChangeServiceStartType(int startType, string serviceName)
162         {
163             try
164             {
165                 RegistryKey regist = Registry.LocalMachine;
166                 RegistryKey sysReg = regist.OpenSubKey("SYSTEM");
167                 RegistryKey currentControlSet = sysReg.OpenSubKey("CurrentControlSet");
168                 RegistryKey services = currentControlSet.OpenSubKey("Services");
169                 RegistryKey servicesName = services.OpenSubKey(serviceName, true);
170                 servicesName.SetValue("Start", startType);
171             }
172             catch (Exception)
173             {
174                 throw;
175             }
176         }
177         #endregion
178
179         #region 启动服务
180         /// <summary>
181         /// 启动服务
182         /// </summary>
183         /// <param name="serviceName">服务名</param>
184         /// <param name="param">参数</param>
185         /// <returns></returns>
186         public static bool StartService(string serviceName, string[] param)
187         {
188             try
189             {
190                 bool flag = true;
191                 if (IsServiceExisted(serviceName))
192                 {
193                     System.ServiceProcess.ServiceController service = new System.ServiceProcess.ServiceController(serviceName);
194                     if (service.Status != System.ServiceProcess.ServiceControllerStatus.Running && service.Status != System.ServiceProcess.ServiceControllerStatus.StartPending)
195                     {
196                         service.Start(param);
197                         for (int i = 0; i < 60; i++)
198                         {
199                             service.Refresh();
200                             System.Threading.Thread.Sleep(1000);
201                             if (service.Status == System.ServiceProcess.ServiceControllerStatus.Running)
202                             {
203                                 break;
204                             }
205                             if (i == 59)
206                             {
207                                 flag = false;
208                             }
209                         }
210                     }
211                 }
212                 return flag;
213             }
214             catch (Exception)
215             {
216                 throw;
217             }
218         }
219         #endregion
220
221         #region 停止服务
222         /// <summary>
223         /// 停止服务
224         /// </summary>
225         /// <param name="serviceName">服务名</param>
226         /// <returns></returns>
227         public static bool StopService(string serviceName)
228         {
229             try
230             {
231                 bool flag = true;
232                 if (IsServiceExisted(serviceName))
233                 {
234                     System.ServiceProcess.ServiceController service = new System.ServiceProcess.ServiceController(serviceName);
235                     if (service.Status == System.ServiceProcess.ServiceControllerStatus.Running)
236                     {
237                         service.Stop();
238                         for (int i = 0; i < 60; i++)
239                         {
240                             service.Refresh();
241                             System.Threading.Thread.Sleep(1000);
242                             if (service.Status == System.ServiceProcess.ServiceControllerStatus.Stopped)
243                             {
244                                 break;
245                             }
246                             if (i == 59)
247                             {
248                                 flag = false;
249                             }
250                         }
251                     }
252                 }
253                 return flag;
254             }
255             catch (Exception)
256             {
257                 throw;
258             }
259         }
260         #endregion
261     }
262 }

ServiceHelper.cs

3、为服务传递参数

有时,我们在启动服务时需要设定一些参数,但这些参数如何从调用服务的程序传递给服务呢?

细心的朋友可能已经发现,在第2节中的启动服务方法,需要传递参数param,这是因为ServiceController.Start有两个重载,一个无参数,一个可以传递字符串数组作为参数,这个参数将在服务启动时被OnStart方法接收,这样就实现了为服务传递参数。

4、其他注意事项

①服务安装后被安装的exe文件就被锁定,此时再Build项目将报错,正确的方法是先卸载手动服务,再重新Build

②首先明确概念:

当前工作目录——进行某项操作的目的目录,会随着OpenFileDialog、FileStream等对象所确定的目录而改变。
当前执行目录——该进程从中启动的目录,即文件自身所在目录。

工作目录与执行目录可以不同,例如一个人住在北京,但他的工作地点不一定在北京,可能在天津。

服务安装后其工作目录将变为"C:\Windows\system32",因此如果要使用OpenFileDialog、FileStream等System.IO命名空间下类和方法,并且使用相对路径,请先将工作目录设置到你想要的位置。而此时执行目录还是exe文件所在的文件夹,所以可以赋值给工作目录

③服务中使用工具箱生成的Timer控件,其事件将不会被触发,因此应该手写Timer控件及其事件,如本文第1节中的代码

④服务已经安装,但服务的执行文件发生了变化,此时可能出现卸载不掉的情况

可以以管理员方式打开CMD,执行以下命令卸载服务:sc delete 服务名

时间: 2024-11-05 15:51:07

WindowsService服务的C#实现的相关文章

WindowsService服务安装脚本

安装脚本%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe D:\liuyl\WeiXinService\WindowsService.exenet start WXServicesc config WXService start= auto WXService 是服务的名称 卸载脚本 %SystemRoot%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe -u D

VS2010 创建WindowsService服务

1.新建一个Windows 服务 2.添加Installer 这一步很重要,在处理完你的业务逻辑后需要添加一个Installer才能是你的Windows服务被安装. 在VS中添加Installer 右键你的Service服务,选择View Designer 再在View Designer视图中右键Add Installer 这样Installer就添加好了. 3.设置服务参数 在添加Installer时会自动生成一个ProjectInstaller.cs,在这个文件中有个InitializeCo

WindowsService 安装后报错: 无法启动计算机“.”上的服务 解决方案

问题 : 根据客户的需求做了一个小程序,需要有对WindowsService 安装,卸载,启动,停止的操作. 编译好之后在我的工程内直接Run 没问题.直接在\bin\Debug 点小程序运行,任何操作也没问题. 由于客户要求免安装. 于是我把Debug 文件夹拷到桌面上运行,其他功能都ok,但是涉及到WindowsService的时候启动总是报错:“无法启动计算机“.”上的服务”. 追错思路:于是桌面上程序的安装好了服务之后:1.用bin文件夹下的程序来启动也是这个错:2,用工程直接跑起来启动

WindowsService(Windows服务)开发步骤附Demo

1.打开VS,新建项目,选择Windows服务,然后设置目录及项目名称后点击确定. 2.展开Service1服务文件,编写service1.cs类文件,不是Service1[设计].然后修改OnStart和OnStop方法. 3.编写服务代码,这里不多说,实现简单写日志的功能...看代码,如不明白,看Demo 4.配置WindowsService安装程序.切换到设计视图,单击右键,出现菜单,单击添加安装程序. 5.在安装程序界面,选择**ProcessInstaller1,然后F4查看属性,Ac

WindowsService(Windows服务)开发步骤附Demo 【转】

转http://www.cnblogs.com/moretry/p/4149489.html 1.打开VS,新建项目,选择Windows服务,然后设置目录及项目名称后点击确定. 2.展开Service1服务文件,编写service1.cs类文件,不是Service1[设计].然后修改OnStart和OnStop方法. 3.编写服务代码,这里不多说,实现简单写日志的功能...看代码,如不明白,看Demo 4.配置WindowsService安装程序.切换到设计视图,单击右键,出现菜单,单击添加安装

使用WindowsService为宿主实装WCF 服务

1. 写WCF服务   创建一个接口类,与一个实现类.接口类上打上[ServiceContract]标签,需要暴露的服务方法上打上[OperationContract] (注意:增加System.ServiceModel 类的引用 代码如下: [csharp] view plaincopy using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Servi

Window环境下配置Redis服务的方法及查看缓存数据的工具介绍

工具下载位置:http://pan.baidu.com/s/1hqVh1f2,包括服务端配置以及查看缓存的工具. 服务端是以服务的形式运行,将Redis服务端解压到某个目录,然后执行cmd执行命令: redis-server.exe --service-install redis.windows.conf --loglevel verbose 注意事项,修改Redis端口及密码的配置在文件redis.windows-service.conf中:(使用redis284.rar中解压文件) 修改端口

使用ASP.NET实现定时计划任务,不依靠windows服务

我们怎样才能在服务器上使用asp.net定时执行任务而不需要安装windows service?我们经常需要运行一些维护性的任务或者像发送提醒邮件给用户这样的定时任务.这些仅仅通过使用Windows Service就可以完成.Asp.net通常是一个无状态的提供程序,不支持持续运行代码或者定时执行某段代码.所以,我们不得不构建自己的windows service来运行那些定时任务.但是在一个共享的托管环境下,我们并不总是有机会部署我们自己的windwos service到我们托管服务提供商的we

window服务创建

第一步:创建服务 第二步:在Service1.cs视图中 右键 选择”添加安装程序” 这里要注意几个细节 设置上面的属性 这两个分别有属性,具体网上查使用方式 3 实例代码编写 主要下面几个方法 protected override void OnStart(string[] args)        {                       timer.Interval = 1000 * 60*24;            timer.Elapsed += new System.Time