[DoNet]自动化部署WinService

四 21st, 2011

     现在进入到项目的后期,主要是解决一些bug,并维护其中WCF和WinService服务。目前我们的产品有test,Dev,Test_build,release,四个版本。只要有一点的改动,对于我们的WinService服务就得进行升级,不然就会出现问题。在经历了几次手动的操作之后,我开始感觉到这太浪费时间,于是我就开始做了一个小工具进行维护这个服务。

我的思路:

1. 将Service程序与安装程序分离开,规划好四个不同的安装路径,分别放置不同的版本。

2. 先在服务器上安装好service,分别取名为**_Dev, ***_Test,….

3.  当有新的组件需要覆盖原有的服务时,需停止当前的service。

4. 利用xcopy将新的文件覆盖当前服务运行的程序。

5. 最后重启改服务,运行几个小case,进行简单的测试,确保服务正常运行。

前面2个步骤都是已经存在的,不需要再做改动,所以我的工具中需要的是后面三个步骤的操作。

对于服务的管理,DoNet提供了2个类,一个是System.ServiceProcess,另一个是System.Management。

之前我利用ServiceProcess,写了2个函数,分别用在启动和停止服务,但是碰到的问题是对于没有权限的服务,没法输入用户名和密码进行验证并打开。导致我只有改服务运行的权限,这种方案不是很好。

接着我就利用Management,重新写了一套启动和停止服务的类,用以实现权限验证的目的。参考下面的类:

 //可以管理和操作服务器上的服务,可以通过用户名和密码进行验证,当服务器为本机的时候,用户名和密码为空
    class ManagementSample
    {
        private String path = String.Empty;
        private ManagementClass managementClass = null;

        ///  /// <summary>
        /// 构造函数
        /// </summary>
        /// /// 主机名称或IP地址
        /// 用户名
        /// 密码
        /// 服务名
        public ManagementSample(String Host, String UserName, String Password)
        {
            path = "\\\\" + Host + "\\root\\cimv2:Win32_Service";
            //machineName = BindServiceName;
            managementClass = new ManagementClass(path);
            ConnectionOptions CO = new ConnectionOptions();
            if (!string.IsNullOrEmpty(UserName))
            {
                CO.Username = UserName;
                CO.Password = Password;
            }
            ManagementScope ManagementScope = new ManagementScope("\\\\" + Host + "\\root\\cimv2", CO);
            managementClass.Scope = ManagementScope;
        }
        
        /// <summary>
        /// 获取指定服务的状态
        /// </summary>
        /// <returns>返回Service当前的状态</returns>
        public String GetServiceState(string serviceName)
         {
             foreach (ManagementObject MO in
                 managementClass.GetInstances().Cast<ManagementObject>().Where(MO => MO["Name"].ToString() == serviceName))
             {
                 return MO["State"].ToString();
             }
             return String.Empty;
         }

        /// <summary>
        /// 测试连接
        /// </summary>
        /// <returns>成功返回True,不成功返回False</returns>
        public bool RemoteConnectValidate()
        {
            if (managementClass == null)
                return false;
            try
            {
                managementClass.Scope.Connect();
            }
            catch
            {
            }
            return managementClass.Scope.IsConnected;
        }


        /// <summary>
        /// 启动指定的Service
        /// </summary>
        /// <returns>成功返回True,不成功返回False</returns>
        public string StartService(string serviceName)
        {
            string strRst = string.Empty;
            ManagementObject mo = this.managementClass.CreateInstance();
            if (mo != null)
            {
                mo.Path = new ManagementPath(this.path + ".Name=\"" + serviceName + "\"");
                try
                {
                    
                    if ((string)mo["State"] == "Stopped")
                    {
                        Console.WriteLine(DateTime.Now + " Start service " + serviceName + "...");
                        mo.InvokeMethod("StartService", null);
                        Console.WriteLine(DateTime.Now + " Start service " + serviceName + " finished");
                    }
                    System.Threading.Thread.Sleep(1000); // sleep 10 sec to wait the current service status update.
                    Console.WriteLine(DateTime.Now.ToString() + " The " + serviceName + " service status is " + (string)mo["State"]);
                }
                catch (ManagementException e)
                {
                    strRst = e.Message;
                }
            }
            return strRst;  
        }

        public string StopService(string serviceName)
        {
            string strRst = string.Empty;
            ManagementObject mo = this.managementClass.CreateInstance();
            if (mo != null)
            {
                mo.Path = new ManagementPath(this.path + ".Name=\"" + serviceName + "\"");
                try
                {
                    if ((string)mo["State"] == "Started")
                    {
                        Console.WriteLine(DateTime.Now + " Stop service " + serviceName + "...");
                        mo.InvokeMethod("StopService", null);
                        Console.WriteLine(DateTime.Now + " Stop service " + serviceName + " finished");
                    }
                    System.Threading.Thread.Sleep(1000); // sleep 10 sec to wait the current service status update.
                    Console.WriteLine(DateTime.Now.ToString() + " The " + serviceName + " service status is " + (string)mo["State"]);
                }
                catch (ManagementException e)
                {
                    strRst = e.Message;
                }
            }
            return strRst;  
        }
    }

然后就是最重要的就是文件的拷贝了,下面的代码实现的功能就是实现服务器与本地文件的拷贝工作:

//FileCopy(@"\\服务器名或IP\coursebackup\",@"e:\course\files");
        public static string FileCopy(string destDir,string sourceDir)
        {
            string command = @"xcopy /s/y/f " + sourceDir + @"\*.* " + destDir + @"\*.*";
            Process proc = new Process
                               {
                                   StartInfo =
                                       {
                                           FileName = "cmd.exe",
                                           Arguments = "/c" + command,
                                           CreateNoWindow = false,
                                           UseShellExecute = false,
                                           RedirectStandardInput = true,
                                           RedirectStandardOutput = true,
                                           RedirectStandardError = true
                                       }
                               };
            proc.Start();
            return proc.StandardOutput.ReadToEnd();
        }

 

之前,我利用ServiceProcess写的两个用于操作服务的函数,参看下面的代码:

  //目前还没找到方案支持操作特定权限的服务,可以同时操作多个服务
    class ServiceControllerSample
    {
        /// <summary>
        /// 服务启动
        /// </summary>
        /// <param name="machine">服务所在机器的IP或者名称</param>
        /// <param name="services">服务名</param>
        public static void StartServices(string machine, string[] services)
        {
            if (string.IsNullOrEmpty(machine) || (services == null) || (services.Length == 0))
            {
                throw new ArgumentNullException();
            }
            else
            {
                try
                {
                    foreach (string service in services)
                    {
                        //If it is stopped, start the service. 
                        var sc = new ServiceController(service) { MachineName = machine };

                        if ((sc.Status.Equals(ServiceControllerStatus.Stopped)) ||
                            (sc.Status.Equals(ServiceControllerStatus.StopPending)))
                        {
                            //Start the service if the current status is stopped. 
                            Console.WriteLine(DateTime.Now + " Start service " + service + "...");
                            sc.Start();
                            Console.WriteLine(DateTime.Now + " Start service " + service + " finished");
                        }

                        //   Refresh and display the current service status. 
                        sc.Refresh();
                        System.Threading.Thread.Sleep(1000); // sleep 10 sec to wait the current service status update.
                        Console.WriteLine(DateTime.Now.ToString() + " The " + service + " service status is " +
                                          sc.Status);
                    }
                }
                catch (Exception ex)
                {
                    throw new ArgumentException(ex.Message);
                }
            }
        }

        /// <summary>
        /// 服务停止
        /// </summary>
        /// <param name="machine">服务所在机器的IP或者名称</param>
        /// <param name="services">服务名</param>
        public static void StopServices(string machine, string[] services)
        {
            if (string.IsNullOrEmpty(machine) || (services == null) || (services.Length == 0))
            {
                throw new ArgumentNullException();
            }
            else
            {
                try
                {
                    foreach (string service in services)
                    {
                        //If it is stopped, start the service. 
                        var sc = new ServiceController(service) { MachineName = machine };

                        if ((sc.Status.Equals(ServiceControllerStatus.Running)) ||
                            (sc.Status.Equals(ServiceControllerStatus.StartPending)))
                        {
                            //Start the service if the current status is stopped. 
                            Console.WriteLine(DateTime.Now + " Stop service " + service + "...");
                            sc.Stop();
                            Console.WriteLine(DateTime.Now + " Stop service " + service + " finished");
                        }

                        //   Refresh and display the current service status. 
                        sc.Refresh();
                        System.Threading.Thread.Sleep(1000); // sleep 10 sec to wait the current service status update.
                        Console.WriteLine(DateTime.Now.ToString() + " The " + service + " service status is " +
                                          sc.Status);
                    }
                }
                catch (Exception ex)
                {
                    throw new ArgumentException(ex.Message);
                }
            }
        }
  
    }




除非注明,本站文章均为原创。本文基于 BY-NC-SA 协议进行授权,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 metaboy(包含链接).

本文链接地址: http://blog.wangyuxiong.com/archives/51132

订阅本站:http://www.wangyuxiong.com/feed

分类: 语言编程         标签: , ,
  1. Ralph Lauren Polo Shirts
    七 23rd, 201301:20

    I’ve been surfing online more than 3 hours today, yet I never found any interesting article like yours. It’s pretty worth enough for me. In my view, if all webmasters and bloggers made good content as you did, the web will be a lot more useful than ever before.

无觅相关文章插件,快速提升流量