zoukankan      html  css  js  c++  java
  • C# 远程服务器 安装、卸载 Windows 服务,读取远程注册表,关闭杀掉远程进程

    这里安装windows服务我们用sc命令,这里需要远程服务器IP,服务名称、显示名称、描述以及执行文件,安装后需要验证服务是否安装成功,验证方法可以直接调用ServiceController来查询服务,也可以通过远程注册表来查找服务的执行文件;那么卸载文件我们也就用SC命令了,卸载后需要检测是否卸载成功,修改显示名称和描述也用sc命令。至于停止和启动Windows服务我们可以用sc命令也可以用ServiceController的API,当停止失败的时候我们会强制杀掉远程进程,在卸载windows 服务我们需要关闭windows服务窗口,不然无法删除服务(服务被标记为已删除状态)注意安装和卸载Windows服务是通过sc命令来执行的,把sc命令发送到服务器上,服务器需要一段执行时间,所以在远程注册表不一定马上体现安装和卸载的效果,这里我们需要有一个重试的机制远程服务需要引用System.ServiceProcess,关闭远程进程需要引用 System.Management.dll 。先关code如下:

       #region Windows Service 操作
            /// <summary>
            /// 安装Windows 服务
            /// </summary>
            /// <param name="serviceEXEPath">可执行文件的完全路径</param>
            public void Install(string webIp, string serviceName, string displayName, string description, string serviceEXEPath)
            {
                //检查安装文件是否存在
                string remoteFile = PathUtil.GetRemotePath(webIp, serviceEXEPath);
                if (!File.Exists(remoteFile))
                {
                    throw new Exception($"安装文件{serviceEXEPath}在服务器{webIp}上不存在");
                }
                //生成安装指令
                string serviceInstallCommand = $"sc \\{webIp} create {serviceName} binpath= "{serviceEXEPath}" displayname= "{displayName}" start= auto ";
                string updateDescriptionCommand = $"sc \\{webIp} description {serviceName} "{description}" ";
                string[] cmd = new string[] { serviceInstallCommand, updateDescriptionCommand };
                string ss = Cmd(cmd);
                //检查安装是否成功
                string imagePath = GetImagePath(webIp, serviceName);
                int retryTime = 0;
                int maxTime = 3;
                while (retryTime < maxTime && string.IsNullOrEmpty(imagePath))
                {
                    Thread.Sleep(1000 * 30);
                    retryTime++;
                    imagePath = GetImagePath(webIp, serviceName);
                }
                if (string.IsNullOrEmpty(imagePath))
                {
                    throw new Exception($"{serviceName}在{webIp}安装失败,{ss}");
                }
            }
    
            /// <summary>
            /// 卸载Windows 服务
            /// </summary>
            /// <param name="serviceEXEPath">可执行文件的完全路径</param>
            public void Uninstall(string webIp, string serviceName, string serviceEXEPath)
            {
                //关闭mmc.exe进程,如果windows 服务打开 将无法卸载
                var ps = Process.GetProcessesByName(@"mmc", webIp);
                if (ps.Length > 0)
                {
                    CloseProcess(webIp, "mmc.exe", string.Empty);
                }
    
                //检查卸载文件是否存在
                string remoteFile = PathUtil.GetRemotePath(webIp, serviceEXEPath);
                if (!File.Exists(remoteFile))
                {
                    throw new Exception($"卸载文件{serviceEXEPath}在服务器{webIp}上不存在");
                }
    
                //生成卸载命令
                string[] cmd = new string[] { $"sc \\{webIp} stop {serviceName}", $"sc \\{webIp} delete {serviceName}" };
                string ss = Cmd(cmd);
                string imagePath = GetImagePath(webIp, serviceName);
                //检查卸载是否成功
                int retryTime = 0;
                int maxTime = 3;
                while (retryTime < maxTime && !string.IsNullOrEmpty(imagePath))
                {
                    Thread.Sleep(1000 * 30);
                    retryTime++;
                    imagePath = GetImagePath(webIp, serviceName);
                }
                if (!string.IsNullOrEmpty(imagePath))
                {
                    throw new Exception($"{serviceName}在{webIp}卸载失败,{ss}");
                }
            }
    
            /// <summary>
            /// 修改windows 服务的显示名称和描述
            /// </summary>
            /// <param name="webIp"></param>
            /// <param name="serviceName"></param>
            /// <param name="displayName"></param>
            /// <param name="description"></param>
            public void UpdateDisplayNameAndDescription(string webIp, string serviceName, string displayName, string description)
            {
                //检查服务是否存在
                string imagePath = GetImagePath(webIp, serviceName);
                if (string.IsNullOrEmpty(imagePath))
                {
                    throw new Exception($"服务{serviceName}在{webIp}不存在");
                }
                //生成修改指令
                string updateDispalyNameCommand = $"sc \\{webIp} config {serviceName} displayname= "{displayName}"";
                string updateDescriptionCommand = $"sc \\{webIp} description {serviceName} "{description}" ";
                string[] cmd = new string[] { updateDispalyNameCommand, updateDescriptionCommand };
                string ss = Cmd(cmd);
            }
    
            /// <summary>
            /// sc 停止和启动windows服务
            /// </summary>
            /// <param name="webIp"></param>
            /// <param name="serviceName"></param>
            /// <param name="stop"></param>
            public void StopAndStartService(string webIp, string serviceName, bool stop)
            {
                string serviceCommand = $"sc \\{webIp} {(stop ? "stop" : "start")} {serviceName}";//停止或启动服务  
                string[] cmd = new string[] { serviceCommand };
                string ss = Cmd(cmd);
            }
    
            /// <summary>  
            /// 运行CMD命令  
            /// </summary>  
            /// <param name="cmd">命令</param>  
            /// <returns></returns>  
            public string Cmd(string[] cmd)
            {
                Process p = new Process();
                p.StartInfo.FileName = "cmd.exe";
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardInput = true;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.RedirectStandardError = true;
                p.StartInfo.CreateNoWindow = true;
                p.Start();
                p.StandardInput.AutoFlush = true;
                for (int i = 0; i < cmd.Length; i++)
                {
                    p.StandardInput.WriteLine(cmd[i].ToString());
                }
                p.StandardInput.WriteLine("exit");
                string strRst = p.StandardOutput.ReadToEnd();
                p.WaitForExit();
                p.Close();
                return strRst;
            }
    
            /// <summary>
            /// 关闭远程计算机进程
            /// </summary>
            /// <param name="webIp"></param>
            /// <param name="processName"></param>
            public void CloseProcess(string webIp, string processName, string executablePath)
            {
                ConnectionOptions oOptions = new ConnectionOptions();
                oOptions.Authentication = AuthenticationLevel.Default;
                ManagementPath oPath = new ManagementPath($"\\{webIp}\root\cimv2");
                ManagementScope oScope = new ManagementScope(oPath, oOptions);
                ObjectQuery oQuery = new ObjectQuery($"Select * From Win32_Process Where Name = "{processName}"");
                using (ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(oScope, oQuery))
                {
                    foreach (ManagementObject oManagementObject in oSearcher.Get())
                    {
                        if (oManagementObject["Name"].ToString().ToLower() == processName.ToLower())
                        {
                            /*
                                foreach (PropertyData prop in oManagementObject.Properties)
                                {
                                    Console.WriteLine($"      {prop.Name} -- -  {prop.Value } ");
                                }
                             */
                            string path = oManagementObject["ExecutablePath"].ToString();
                            if (string.IsNullOrEmpty(executablePath) || path == executablePath)
                            {
                                oManagementObject.InvokeMethod("Terminate", new object[] { 0 });
                            }
                        }
                    }
                }
            }
    
            /// <summary>
            /// 获取远程计算机 服务的执行文件
            /// </summary>
            /// <param name="serverIP">远程计算机IP</param>
            /// <param name="serviceName">远程服务名称</param>
            /// <returns></returns>
            public string GetImagePath(string serverIP, string serviceName)
            {
                string registryPath = @"SYSTEMCurrentControlSetServices" + serviceName;
                using (RegistryKey key = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, serverIP).OpenSubKey(registryPath))
                {
                    if (key == null)
                    {
                        return string.Empty;
                    }
                    string value = key.GetValue("ImagePath").ToString();
                    key.Close();
                    value = value.Trim('"');
                    if (value.Contains("SystemRoot"))
                    {
                        return ExpandEnvironmentVariables(serverIP, value);
                    }
                    return value;
                }
            }
    
            /// <summary>
            /// 替换路径中的SystemRoot
            /// </summary>
            /// <param name="serverIP">远程计算机IP</param>
            /// <param name="path">路径</param>
            /// <returns></returns>
            private string ExpandEnvironmentVariables(string serverIP, string path)
            {
                string systemRootKey = @"SoftwareMicrosoftWindows NTCurrentVersion";
                using (RegistryKey key = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, serverIP).OpenSubKey(systemRootKey))
                {
                    string expandedSystemRoot = key.GetValue("SystemRoot").ToString();
                    key.Close();
                    path = path.Replace("%SystemRoot%", expandedSystemRoot);
                    return path;
                }
            }
    
            /// <summary>
            /// 停止或启动Windows 服务
            /// </summary>
            /// <param name="serviceName">服务名称</param>
            /// <param name="serverIP">远程IP</param>
            /// <param name="stop">是否是停止</param>
            public void StopAndStartWindowsService(string serviceName, string serverIP, bool stop)
            {
                using (ServiceController sc = ServiceController.GetServices(serverIP)
                                .FirstOrDefault(x => x.ServiceName == serviceName))
                {
                    if (sc == null)
                    {
                        throw new Exception($"{serviceName}不存在于{serverIP}");
                    }
                    StopAndStartWindowsService(sc, stop);
    
                    if (stop)
                    {
                        sc.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 1, 0));
                    }
                    sc.Close();
                }
    
    
            }
    
            /// <summary>
            /// 停止或启动Windows 服务
            /// </summary>
            /// <param name="sc"></param>
            /// <param name="stop"></param>
            private void StopAndStartWindowsService(ServiceController sc, bool stop = true)
            {
                Action act = () =>
                {
                    ServiceControllerStatus serviceSate = sc.Status;
                    if (stop && (serviceSate == ServiceControllerStatus.StartPending || serviceSate == ServiceControllerStatus.Running))
                    {
                        //如果当前应用程序池是启动或者正在启动状态,调用停止方法
                        sc.Stop();
                    }
                    if (!stop && (serviceSate == ServiceControllerStatus.Stopped || serviceSate == ServiceControllerStatus.StopPending))
                    {
                        sc.Start();
                    }
                };
                int retryCount = 0;
                int maxCount = 4;
                while (sc != null && retryCount <= maxCount)
                {
                    try
                    {
                        act();
                        break;
                    }
                    catch (Exception ex)
                    {
                        if (stop)
                        {
                            string serverIP = sc.MachineName;
                            string serviceName = sc.ServiceName;
                            var imeagePath = GetImagePath(serverIP, serviceName);
                            FileInfo fileInfo = new FileInfo(imeagePath);
                            CloseProcess(serverIP, fileInfo.Name, fileInfo.FullName);
                        }
                        retryCount++;
                        if (retryCount == maxCount)
                        {
                            throw new Exception($"{(stop ? "停止" : "启动")}Windows服务{sc.ServiceName}出错{ex.Message}");
                        }
                        Thread.Sleep(1000 * 30);
                    }
                }//end while
            }
    
            /// <summary>
            /// 获取windows 服务状态
            /// </summary>
            /// <param name="serviceName">服务名称</param>
            /// <param name="serverIP">服务器IP</param>
            /// <returns></returns>
            public ServiceControllerStatus GetServiceState(string serviceName, string serverIP)
            {
                ServiceControllerStatus serviceSate;
                using (ServiceController sc = ServiceController.GetServices(serverIP)
                                .FirstOrDefault(x => x.ServiceName == serviceName))
                {
                    if (sc == null)
                    {
                        throw new Exception($"{serviceName}不存在于{serverIP}");
                    }
                    serviceSate = sc.Status;
                    sc.Close();
                }
                return serviceSate;
            }
    
            #endregion
  • 相关阅读:
    mac下通过复制启动两个tomcat
    搭建一个redis集群
    ubantu系统下永久修改主机名
    民宿项目知识_截取最后一个逗号
    民宿项目知识_string判断是否为空
    民宿项目知识_enum
    民宿项目中的知识点_动态删除tr
    笔记:迁移来自xinlang的笔记
    SVN使用笔记
    iOS性能优化笔记
  • 原文地址:https://www.cnblogs.com/majiang/p/7534070.html
Copyright © 2011-2022 走看看