1. 程式人生 > >C# 遠程服務器 安裝、卸載 Windows 服務,讀取遠程註冊表,關閉殺掉遠程進程

C# 遠程服務器 安裝、卸載 Windows 服務,讀取遠程註冊表,關閉殺掉遠程進程

llc sat tar time esp remote 是否 emp splay

這裏安裝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

C# 遠程服務器 安裝、卸載 Windows 服務,讀取遠程註冊表,關閉殺掉遠程進程