且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

.net知识和学习方法系列(二十五) .net中的windows service与服务操作

更新时间:2022-03-16 03:49:04


昨天一个朋友想用做个短信网关,与移动TCP/IP通迅来完成短信的发送。并且想是用一个Windows服务来完成这个工作,但是又想让管理员能在客户端(浏览器端)对服务进行装载,卸载,启动,停止。我初步听了以后,觉得这个需求是可以完成的,服务这个项目的建立没有问题,控制服务这个项目也是没有问题的。于是就研究了一下,并去网上搜集了一些资料,整理了一个从技术角度相对完整的文档,拿出来给大家分享一下。

为了简化业务,这里就把与短信网关通信的需求改成每间隔一秒钟向一个txt文档写一个当前时间的需求。
我们先来看服务部分:
打开VS2008,“文件→新建→项目”,选择“Windows”项中的“Windows服务”,根据自己的情况修跑径和名称,这里的名称修为“WriteTextService”,确定后,出现一个“若要在类中添加组件,请从工具箱中拖出它们,然后例用属性窗口来设置它们的属性。若要为类创建方法和事件,请单击此处切换到代码视图。”的一个界面,我们如果处理业务逻辑,单击“单击此处切换到代码视图”,来转换到代码页。
代码
WriteTextService.cs
 
1using System; 
2using System.ServiceProcess; 
3using System.IO; 
4using System.Threading; 

6namespace WriteTextServiceNS 
7{ 
8        public partial class WriteTextService : ServiceBase 
9        { 
10                public WriteTextService() 
11                { 
12                        InitializeComponent(); 
13                } 
14                protected override void OnStart(string[] args) 
15                { 
16                        Thread t = new Thread(new ThreadStart(DY)); 
17                        t.Start();                                            
18                } 
19                private void DY() 
20                { 
21                        while (true) 
22                        { 
23                                File.WriteAllText(@"F:/gsw.txt",DateTime.Now.ToString()); 
24                                Thread.Sleep(2000); 
25                        } 
26                } 
27                protected override void OnStop() 
28                { 
29                } 
30        } 
31} 
32
现在,我们还需要在服务中创建一个服务安装类,来完成服务初始化安装工作。
我们创建一个类ServiceInstall
ServiceInstall.cs
 
1using System.Collections; 
2using System.Configuration.Install; 
3using System.ServiceProcess; 
4using System.ComponentModel; 
5using Microsoft.Win32; 

7namespace WriteTextServiceNS 
8{    
9        [RunInstaller(true)] 
10        public class ServiceInstall : Installer 
11        { 
12                private ServiceInstaller WTSerInst;    //它由安装实用工具用来将与服务关联的注册表值写入 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services 注册表项内的子项。 
13                private ServiceProcessInstaller    WTProInst;    //安装实用工具使用它来写与要安装服务关联的注册表值。 
14                public ServiceInstall() 
15                { 
16                        WTProInst = new ServiceProcessInstaller(); 
17                        WTProInst.Account = ServiceAccount.LocalSystem;    //安装服务时使用的账户 
18                     
19                        WTSerInst = new ServiceInstaller();                         
20                        WTSerInst.StartType = ServiceStartMode.Automatic ; //启动服务的后模式(Automatic 自动,Manual 手动,Disabled 禁用)    
21                        WTSerInst.ServiceName = "WriteTextService";     //要安装服务的名称 与服务类名相同 
22                        
23                        Installers.Add(WTSerInst);    //把服务安装类放入安装集合中 
24                        Installers.Add(WTProInst); 
25                } 
26                /**//// <summary> 
27                /// 重写父类的安装,并在安装服务后写入服务的描述 
28                /// </summary> 
29                /// <param name="stateSaver"></param> 
30                public override void Install(IDictionary stateSaver) 
31                { 
32                        RegistryKey system,service,config; 
33                        try 
34                        { 
35                                base.Install(stateSaver); 
36                                system = Registry.LocalMachine.OpenSubKey("System").OpenSubKey("CurrentControlSet").OpenSubKey("Services"); 
37                                service = system.OpenSubKey(this.WTSerInst.ServiceName, true); 
38                                service.SetValue("Description", "……这是一个每秒写入Text一次时间的服务……");                            
39                                config = service.CreateSubKey("AdditionalInformation"); 
40                        } 
41                        catch 
42                        { } 
43                } 
44                /**//// <summary> 
45                /// 重写父类的卸载,并在卸载服务后删除描述 
46                /// </summary> 
47                /// <param name="stateServer"></param> 
48                public override void Uninstall(IDictionary stateServer) 
49                { 
50                        RegistryKey system,currentControlSet,services,service; 
51                        try 
52                        { 
53                                system = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("System"); 
54                                currentControlSet = system.OpenSubKey("CurrentControlSet"); 
55                                services = currentControlSet.OpenSubKey("Services"); 
56                                service = services.OpenSubKey(this.WTSerInst.ServiceName, true); 
57                                service.DeleteSubKeyTree("AdditionalInformation"); 
58                        } 
59                        catch    
60                        {} 
61                        finally 
62                        { 
63                                base.Uninstall(stateServer); 
64                        } 
65                } 
66        } 
67} 
68
这样就完成了一个服务,关且有服务的描述,最要是通过重写父类Install和Uninstall来完成对服务描述的添加。因为服务都是在HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/WriteTextService下有个项Description,给这个项添加数据就对应该服务的描述,所以Install和Uninstall两个方法本质上就是注册表英的添加与删除。
 
接下来我们看一下服务的操作,即装载,卸载,启动,停止。
我们新建一个web网站,只有一个Default.aspx页面,代码如下:
Default.aspx
 
1<%@ Page Language="C#" AutoEventWireup="true"    CodeFile="Default.aspx.cs" Inherits="_Default" %> 

3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 

5<html xmlns="http://www.w3.org/1999/xhtml"> 
6<head runat="server"> 
7        <title>无标题页</title> 
8</head> 
9<body> 
10        <form id="form1" runat="server"> 
11        <div> 
12         
13                <asp:Button ID="Button1" runat="server" Text="装载服务" /> 
14                <asp:Button ID="Button2" runat="server" Text="卸载服务" /> 
15                <asp:Button ID="Button3" runat="server" Text="启动服务" /> 
16                <asp:Button ID="Button4" runat="server" Text="停止服务" /> 
17         
18        </div> 
19        </form> 
20</body> 
21</html> 
22
 
Default.aspx.cs
 
1using System; 
2using System.Configuration; 
3using System.Web; 
4using System.Web.Security; 
5using System.Web.UI; 
6using System.Web.UI.HtmlControls; 
7using System.Web.UI.WebControls; 
8using System.Web.UI.WebControls.WebParts; 
9using System.Xml.Linq; 
10using System.Configuration.Install; 
11using System.Collections; 
12using System.ServiceProcess; 
13 
14 
15public partial class _Default : System.Web.UI.Page    
16{ 
17        protected void Page_Load(object sender, EventArgs e) 
18        { 
19 
20        } 
21        protected void Button1_Click(object sender, EventArgs e) 
22        { 
23                AssemblyInstaller myassemblyinstaller = new AssemblyInstaller();//加载一个程序集,并运行其中的所有安装程序。 
24                myassemblyinstaller.UseNewContext = true; 
25                myassemblyinstaller.Path = @"f:/gsw.exe";//服务所在的路径 
26                Hashtable mysavedstate = new Hashtable(); 
27                myassemblyinstaller.Install(mysavedstate); 
28                myassemblyinstaller.Commit(mysavedstate); 
29                myassemblyinstaller.Dispose(); 
30                Response.Write("安装服务成功"); 
31         
32        } 
33        protected void Button2_Click(object sender, EventArgs e) 
34        { 
35                AssemblyInstaller myassemblyinstaller = new AssemblyInstaller(); 
36                myassemblyinstaller.UseNewContext = true; 
37                myassemblyinstaller.Path = @"f:/gsw.exe";//服务所在的路径 
38                myassemblyinstaller.CommandLine = new string[1] { "/u" };// 利用/u命令来完成卸载 
39                myassemblyinstaller.Uninstall(null); 
40                myassemblyinstaller.Dispose(); 
41                Response.Write("卸载服务成功"); 
42        } 
43        protected void Button3_Click(object sender, EventArgs e) 
44        { 
45                ServiceController sc = new ServiceController();//表示 Windows 服务并允许连接到正在运行或者已停止的服务、对其进行操作或获取有关它的信息。 
46                sc.DisplayName = "桂素伟"; 
47                sc.ServiceName = "WriteTextService"; 
48                sc.Start();//启动这个名称的服务 
49                System.Threading.Thread.Sleep(1000); 
50                sc.Refresh();//刷新服务的状态 
51                if (sc.Status == ServiceControllerStatus.Running)//判断服务是已经运行 
52                { 
53                    Response .Write ("服务成功启动!"); 
54                } 
55        } 
56        protected void Button4_Click(object sender, EventArgs e) 
57        { 
58                ServiceController sc = new ServiceController(); 
59                sc.ServiceName = "WriteTextService"; 
60                sc.Stop(); 
61                
62                System.Threading.Thread.Sleep(1000); 
63                sc.Refresh();//刷新服务的状态 
64                if (sc.Status == ServiceControllerStatus.Stopped)//判断服务是已经运行 
65                { 
66                     Response .Write ("服务成功停止!"); 
67                } 
68        } 
69} 
70
 
我们是通过AssemblyInstaller类来完成对服务的装载和卸载,通过ServiceController类来完成对服务的启动和停止。
这样,我们就把服务和控制服务的代友做完整了。
(我的代码是在vista和vs2008下实现的。)





















本文转自桂素伟51CTO博客,原文链接: http://blog.51cto.com/axzxs/149945,如需转载请自行联系原作者