码迷,mamicode.com
首页 > Windows程序 > 详细

WindowsService服务的C#实现

时间:2015-03-13 16:21:27      阅读:324      评论:0      收藏:0      [点我收藏+]

标签:

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 服务名

WindowsService服务的C#实现

标签:

原文地址:http://www.cnblogs.com/NaturalSelection/p/4334572.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!