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 = @"SYSTEM\CurrentControlSet\Services\" + 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 = @"Software\Microsoft\Windows NT\CurrentVersion\";
            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
时间: 2024-10-21 20:31:06

C# 远程服务器 安装、卸载 Windows 服务,读取远程注册表,关闭杀掉远程进程的相关文章

安装&amp;卸载Windows服务

使用.NET Framework的工具InstallUtil.exe. 安装服务 C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe MyServer1.exe 启动服务 net start MyServer1 卸载服务 C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe /u MyServer1.exe 一.注意点 安装和卸载必须针对同一个exe,否则

搭建IPA用户管理服务器&安装ssh远程访问服务

1.搭建IPA用户管理服务器 搭建准备前工作 workstation: #先停掉dhcp服务 systemctl stop dhcpd;systemctl disable dhcpd #分别在workstation,server1,server2,database上安装ntp服务 yum -y install ntp #打开ntp配置文件,做如下修改 workstation: vim /etc/ntp.conf 17 restrict 192.168.40.0 mask 255.255.255.

C#创建、安装一个Windows服务

C#创建.安装一个Windows服务http://blog.csdn.net/yysyangyangyangshan/article/details/10515035 关于WIndows服务的介绍,之前写过一篇:http://blog.csdn.net/yysyangyangyangshan/article/details/7295739.可能这里对如何写一个服务不是很详细.现在纯用代码的形式介绍一下windows服务是如何开发和安装的. 开发环境:Win7 32位:工具:visualstudi

使用srvany.exe将程序安装成windows服务的详细教程

srvany.exe介绍 srvany.exe是Microsoft Windows Resource Kits工具集的一个实用的小工具,用于将任何EXE程序作为Windows服务运行.也就是说srvany只是其注册程序的服务外壳,这个特性对于我们 来说非常实用,我们可以通过它让我们的程序以SYSTEM账户启动,或者实现随机器启动而自启动,也可以隐藏不必要的窗口,比如说控制台窗口等等. 资源下载 你可以通过下载并安装Microsoft Windows Resource Kits 获得或者直接在本文

【先定一个小目标】Redis 安装成windows服务-开机自启

1.第一步安装成windows服务的,开机自启动 redis-server --service-install redis.windows.conf 2.启动\关闭 redis-server --service-start redis-server --service-stop 3.可安装多个实例 redis-server --service-install –service-name redisService1 –port 10001 redis-server --service-start

将MongoDB安装为Windows服务---安装MongoDB服务

MongoDB是目前非常流行的一种NoSQL数据库,其灵活的存储方式备受开发人员青睐.本文就介绍一下如何安装并设置成Windows服务的方法.目前为止,我们每次启动MongoDB数据库服务都需要通过CMD输入指令mongod来开启服务,较为麻烦,所以本节介绍下如何将将mongo安装为Windows服务 配置完毕后的启动方式: Win+R 输入 services.msc找到Mongo_Service(这是上面 --serviceName 你填写的服务名称),然后属性,点击启动,然后就好了. 注意:

用 nssm 把 Nginx 安装成 Windows 服务方法

总之:用 nssm 比 srvany.exe 简便多了. 1. 下载nginx windows版本:http://nginx.org/ 2. 下载 nssm :http://nssm.cc/ 3. 安装Nginx下载解压到一个目录,nssm下载后解压相应版本(32/64)到一个目录.然后安装服务:nssm install N1 "D:\N1\nginx.exe" 即可安装成功最基本的服务,不过启动的是nssm,让后由nssm启动nginx. 现在就可以通过控制面板->管理员工具-

将 tomcat 安装成 windows 服务

1.下载 tomcat 的windows 压缩包,一般以 .zip ,而且文件名中有 bin 的文件就是 2.解压下载的文件到某一个目录下,eg: TOMCAT_HOME 3.打开 cmd ,运行 %TOMCAT_HOME%/bin/service.bat install 即可将 tomcat 安装成为 windows 服务 4.服务管理窗口(开始 -> 运行 -> cmd ->  services.msc ),找到 apache tomcat 服务(可以在 service.bat 中重

使用instsrv.exe+srvany.exe将应用程序安装为windows服务[转]

转自:http://qingmu.blog.51cto.com/4571483/1248649 一.什么是instsrv.exe和srvany.exe instsrv.exe.exe和srvany.exe是Microsoft Windows Resource Kits工具集中 的两个实用工具,这两个工具配合使用可以将任何的exe应用程序作为window服务运行.srany.exe是注册程序的服务外壳,可以通过它让应用程序以system账号启动,可以使应用程序作为windows的服务随机器启动而自