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
  • 相关阅读:
    53. Maximum Subarray
    64. Minimum Path Sum
    28. Implement strStr()
    26. Remove Duplicates from Sorted Array
    21. Merge Two Sorted Lists
    14. Longest Common Prefix
    7. Reverse Integer
    412. Fizz Buzz
    linux_修改域名(centos)
    linux_redis常用数据类型操作
  • 原文地址:https://www.cnblogs.com/majiang/p/7534070.html
Copyright © 2011-2022 走看看