当前位置:首页 » 电脑基础知识

部署windows服务

2014-04-09 09:11 本站整理 浏览(5)

部署windows服务--制作安装包

(1)、建立一个新的windows服务项目Server1

(2)、打开Service1代码视图,找到OnStart部分,加入代码

(3)、切换到设计视图,右键-添加安装程序

(4)、切换到新生成的ProjectInstaller.cs设计视图,找到serviceProcessInstaller1对Account属性设置为LocalSystem,对serviceInstaller1的ServiceName属性设置为Server1(服务的名字),StartType属性设置为Automatic(系统启动的时候自动启动服务)

(5)、建立一个新的安装项目ServerSetup(我们为刚才那个服务建立一个安装项目)

(6)、右键-添加-项目输出-主输出-选择Service1-确定

(7)、右键-视图-自定义操作-自定义操作上右键-添加自定义操作-打开应用程序文件夹-选择刚才那个主输出-确定

(8)、重新生成这个安装项目-右键-安装

(9)、在服务管理器中(我的电脑-右键-管理-服务和应用程序-服务)找到Server1服务,启动服务

部署windows服务--通过命令行安装

(1).打开vs.net命令行工具

(2).改变路径到你项目所在的bin\Debug文件夹位置(如果你以Release模式编译则在bin\Release文件夹)

(3).执行命令“InstallUtil.exe MyWindowsService.exe”注册这个服务,使它建立一个合适的注册项。

(4).右击桌面上“我的电脑”,选择“管理”就可以打计算机管理控制台

(5). 在“服务和应用程序”里面的“服务”部分里,你可以发现你的Windows服务已经包含在服务列表当中了

(6). 右击你的服务选择启动就可以启动你的服务了

制作安装包:

OK,逻辑部分已经完成了,下面看关键的操作,将服务打包,首先在本解决方案中添加安装部署项目,

创建安装项目以后是这个样子的:

在应用程序文件夹中添加项目输出:

选择SocketServer作为主输出:

创建自定义操作:

选择自定义操作进入到自定义操作界面,在自定义操作上选择添加自定义操作:

在弹出的选择项目中的项对话框中选择应用程序文件夹中选择主输出项目:

然后分别重新生成SocketServer和SocketSetUp项目,查看解决方案的属性,

查看项目的配置,到对应的文件中去找安装文件,如果是Debug那么就去对应项目中的Debug目录下去找生成的文件,我们的目录是F:\SocketServer,所以得去F:\SocketServer\SocketSetUp\Debug目录去找安装文件。

下面安装一下看一下结果。(/ □ \),在安装的时候让我填写服务器名称密码什么的

,按说我自己在电脑上装东西应该不需要授权啊,回头在看一下,问题出在安装程序上,看到serviceProcessInstaller1的属性的时候发现了授权的信息,Account这个选项中选择LocalSystem应该就是本地安装应该是权限最大的不需要额外授权。试试看吧。OK没有问题,安装成功。下面看一下咱们的逻辑是不是正确,先看已安装程序中是不是存在SocketSetUp程序

没问题,下面在看一下我们SocketServer Release服务是不是运行正常:

没问题,查看8888端口是不是处于监听状态:

没问题,运行一下Socket客户端,看一下结果:

没问题,这样就算成功了,但是有个问题,由于服务所要开放的端口很多时候都是需要用户在安装的时候指定,那好吧,现在将Socke服务端的端口由用户指定。

在安装项目的视图中选择用户界面,在启动选项上右键添加对话框:

在弹出的添加对话框中选择文本框,设置文件框的属性:

这样文本框就添加完了,文本框属性很简单的可以看出来,只需要一个,其他的都隐藏就好了,下面就如何获取用户输入的端口值,在自定义操作中的主输出xxxxx的属性选项卡中添加参数

下面只等着接收了,接收之后将指定的端口保存到本地的安装目录,这样还需要设置一个安装路径的参数应该是这样/Port="[PORT]" /targetdir="[TARGETDIR]/"

俺写了一个XML的帮助类,用来保存端口:

1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Xml;
 6 
 7 namespace SocketServer
 8 {
 9     class XmlHandle
10     {
11         public void updatePort(string path, string port)
12         {
13             try
14             {
15                 XmlTextWriter xmlWriter = new XmlTextWriter(path + "\\server.config", Encoding.UTF8);
16                 xmlWriter.WriteStartDocument();
17                 xmlWriter.WriteStartElement("Server");
18 
19                 xmlWriter.WriteStartElement("port", "");
20                 xmlWriter.WriteString(port);
21                 xmlWriter.WriteEndElement();
22 
23                 xmlWriter.WriteEndDocument();
24                 xmlWriter.Close();
25             }
26             catch (Exception ex)
27             {
28 
29             }
30         }
31 
32 
33         public static string getPort()
34         {
35             string port = "8888";
36             try
37             {
38                 XmlDocument doc = new XmlDocument();
39                 doc.Load(AppDomain.CurrentDomain.BaseDirectory + "\\server.config");
40 
41                 XmlNode xnRoot = doc.SelectSingleNode("Server");
42                 XmlNodeList xnl = xnRoot.ChildNodes;
43                 foreach (XmlNode xn in xnl)
44                 {
45                     XmlElement xe = (XmlElement)xn;
46                     byte[] bts = Encoding.UTF8.GetBytes(xe.Name);
47                     if (xe.Name == "port")
48                     {
49                         port = xe.InnerText;
50                         byte[] bt = Encoding.UTF8.GetBytes(port);
51                         break;
52                     }
53                 }
54 
55             }
56             catch (Exception ex)
57             {
58 
59             }
60             return port;
61         }
62     }
63 }

在ProjectInstaller中处理其中的逻辑,如果需要安装完成以后马上运行,那么就需要这样:

1 using System;
 2 using System.Collections;
 3 using System.Collections.Generic;
 4 using System.ComponentModel;
 5 using System.Configuration.Install;
 6 using System.Linq;
 7 
 8 
 9 namespace SocketServer
10 {
11     [RunInstaller(true)]
12     public partial class ProjectInstaller : System.Configuration.Install.Installer
13     {
14         string port = "";
15         public ProjectInstaller()
16         { 
17             InitializeComponent();
18         }
19 
20         protected override void OnBeforeInstall(IDictionary savedState)
21         {
22             //从用户界面获取的参数
23             port = Context.Parameters["Port"];
24         }
25 
26         protected override void OnAfterInstall(IDictionary savedState)
27         {
28             string appPath = Context.Parameters["targetdir"];
29             XmlHandle xml = new XmlHandle();
30             xml.updatePort(appPath, port);
31             System.ServiceProcess.ServiceController sc = new System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName);
32             if (sc != null)
33             {
34                 sc.Start();
35             }
36         }
37     }
38 }

这样就在服务安装以后服务就能启动,但是在服务启动的时候,需要从本地的配置中获取端口号,那么就需要在SocketHandle.cs中做一点点修改,改成如下的样子:

1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Net.Sockets;
  6 using System.Net;
  7 using System.Threading;
  8 
  9 namespace SocketServer
 10 {
 11     class SocketHandle
 12     {
 13           
 14         private string pointStr = XmlHandle.getPort();
 15         private static Socket serverSocket;
 16         int pointInt = 8888;
 17         private static byte[] result = new byte[1024];
 18         private static SocketHandle socketHandle;
 19 
 20         public SocketHandle()
 21         {
 22 
 23         }
 24 
 25         public static SocketHandle getInstance()
 26         {
 27             if (socketHandle == null)
 28             {
 29                 socketHandle = new SocketHandle();
 30             }
 31 
 32             return socketHandle;
 33         }
 34 
 35         public void InitSocketServer()
 36         {
 37             IPAddress localIp = GetLocalIP();
 38             if (localIp == null)
 39             {
 40                 localIp = IPAddress.Parse("127.0.0.1");
 41             }
 42             try
 43             {
 44                 if (serverSocket == null)
 45                 {
 46                     if (pointStr is string)
 47                     {
 48                         pointInt = Int32.Parse(pointStr);
 49                     }  
 50                     serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);                  
 51                     serverSocket.Bind(new IPEndPoint(localIp, pointInt));
 52                     serverSocket.Listen(10);
 53                     Thread myThread = new Thread(ListenClientConnect);
 54                     myThread.Start(); 
 55 
 56                 }
 57             }
 58             catch (Exception ex)
 59             { 
 60             }
 61         }
 62 
 63 
 64 
 65         /// <summary>  
 66         /// 监听客户端连接  
 67         /// </summary>  
 68         private static void ListenClientConnect()
 69         {
 70             while (true)
 71             {
 72                 try
 73                 {
 74                     Socket clientSocket = serverSocket.Accept();
 75                     Thread receiveThread = new Thread(ReceiveMessage);
 76                     receiveThread.Start(clientSocket);
 77                 }
 78                 catch (Exception ex)
 79                 { 
 80                 }
 81             }
 82         }
 83 
 84 
 85 
 86         /// <summary>  
 87         /// 接收消息  
 88         /// </summary>  
 89         /// <param name="clientSocket"></param>  
 90         private static void ReceiveMessage(object clientSocket)
 91         {
 92             Socket myClientSocket = (Socket)clientSocket; 
 93             byte[] bs = new byte[1024];
 94             while (true)
 95             {
 96                 try
 97                 {
 98                     //通过clientSocket接收数据  
 99                     int receiveNumber = myClientSocket.Receive(result);
100                     string data = Encoding.ASCII.GetString(result, 0, receiveNumber);
101                     bs = Encoding.ASCII.GetBytes("Receive Data "+data);
102                 }
103                 catch (Exception ex)
104                 {
105                     myClientSocket.Shutdown(SocketShutdown.Both);
106                     myClientSocket.Send(bs, bs.Length, 0);  //返回信息给客户端
107                     myClientSocket.Close(); 
108                     break;
109                 }
110                 myClientSocket.Send(bs, bs.Length, 0);
111                 myClientSocket.Close();
112                 break;
113             }
114 
115         }
116 
117         /// <summary>
118         /// 获取本地IP地址
119         /// </summary>
120         /// <returns></returns>
121         private IPAddress GetLocalIP()
122         {
123             IPAddress localIp = null;
124             try
125             {
126                 IPAddress[] ipArray;
127                 ipArray = Dns.GetHostAddresses(Dns.GetHostName());
128 
129                 localIp = ipArray.First(ip => ip.AddressFamily == AddressFamily.InterNetwork);
130             }
131             catch (Exception ex)
132             { 
133             }
134 
135             return localIp;
136         }
137     }
138 }

下面运行一下,在看一下结果:

在服务的安装界面出现了添加端口的输入框:

看端口:

没问题,再看Socket客户端:

没问题。大概就是这样样子,如果大家觉得有什么地方不妥,或者有好的建议或者意见的话希望能够告诉我。谢谢。