前言
在我们的工作中,经常遇到Windows服务的安装和卸载,在之前公司也普写过一个WinForm程序选择安装路径,这次再来个小巧灵活的控制台程序,不用再选择,只需放到需要安装服务的目录中运行就可以实现安装或卸载。
开发思路
1、由于系统的权限限制,在运行程序时需要以管理员身份运行
2、因为需要实现安装和卸载两个功能,在程序运行时提示本次操作是安装还是卸载 需要输入 1 或 2
3、接下来程序会查找当前目录中的可执行文件并过滤程序本身和有时我们复制进来的带有vhost的文件,并列出列表让操作者选择(一般情况下只有一个)
4、根据用户所选进行安装或卸载操作
5、由于可能重复操作,需要递归调用一下
具体实现
首先们要操作服务,需要用 System.ServiceProcess 来封装实现类
1 using System; 2 using System.Collections; 3 using System.Configuration.Install; 4 using System.Linq; 5 using System.ServiceProcess; 6 7 namespace AutoInstallUtil 8 { 9 public class SystemServices 10 { 11 ///12 /// 打开系统服务 13 /// 14 /// 系统服务名称 15 ///16 public static bool SystemServiceOpen(string serviceName) 17 { 18 try 19 { 20 using (var control = new ServiceController(serviceName)) 21 { 22 if (control.Status != ServiceControllerStatus.Running) 23 { 24 control.Start(); 25 } 26 } 27 return true; 28 } 29 catch 30 { 31 return false; 32 } 33 } 34 35 36 /// 37 /// 关闭系统服务 38 /// 39 /// 系统服务名称 40 ///41 public static bool SystemServiceClose(string serviceName) 42 { 43 try 44 { 45 using (var control = new ServiceController(serviceName)) 46 { 47 48 if (control.Status == ServiceControllerStatus.Running) 49 { 50 control.Stop(); 51 } 52 } 53 return true; 54 } 55 catch 56 { 57 return false; 58 } 59 } 60 61 /// 62 /// 重启系统服务 63 /// 64 /// 系统服务名称 65 ///66 public static bool SystemServiceReStart(string serviceName) 67 { 68 try 69 { 70 using (var control = new ServiceController(serviceName)) 71 { 72 if (control.Status == System.ServiceProcess.ServiceControllerStatus.Running) 73 { 74 control.Continue(); 75 } 76 } 77 return true; 78 } 79 catch 80 { 81 return false; 82 } 83 } 84 85 /// 86 /// 返回服务状态 87 /// 88 /// 系统服务名称 89 ///1:服务未运行 2:服务正在启动 3:服务正在停止 4:服务正在运行 5:服务即将继续 6:服务即将暂停 7:服务已暂停 0:未知状态 90 public static int GetSystemServiceStatus(string serviceName) 91 { 92 try 93 { 94 using (var control = new ServiceController(serviceName)) 95 { 96 return (int)control.Status; 97 } 98 } 99 catch100 {101 return 0;102 }103 }104 105 ///106 /// 返回服务状态107 /// 108 /// 系统服务名称109 ///1:服务未运行 2:服务正在启动 3:服务正在停止 4:服务正在运行 5:服务即将继续 6:服务即将暂停 7:服务已暂停 0:未知状态 110 public static string GetSystemServiceStatusString(string serviceName)111 {112 try113 {114 using (var control = new ServiceController(serviceName))115 {116 var status = string.Empty;117 switch ((int)control.Status)118 {119 case 1:120 status = "服务未运行";121 break;122 case 2:123 status = "服务正在启动";124 break;125 case 3:126 status = "服务正在停止";127 break;128 case 4:129 status = "服务正在运行";130 break;131 case 5:132 status = "服务即将继续";133 break;134 case 6:135 status = "服务即将暂停";136 break;137 case 7:138 status = "服务已暂停";139 break;140 case 0:141 status = "未知状态";142 break;143 }144 return status;145 }146 }147 catch148 {149 return "未知状态";150 }151 }152 153 ///154 /// 安装服务155 /// 156 /// 157 /// 158 public static void InstallService(IDictionary stateSaver, string filepath)159 {160 try161 {162 var myAssemblyInstaller = new AssemblyInstaller163 {164 UseNewContext = true,165 Path = filepath166 };167 myAssemblyInstaller.Install(stateSaver);168 myAssemblyInstaller.Commit(stateSaver);169 myAssemblyInstaller.Dispose();170 }171 catch (Exception ex)172 {173 throw new Exception("installServiceError/n" + ex.Message);174 }175 }176 177 public static bool ServiceIsExisted(string serviceName)178 {179 ServiceController[] services = ServiceController.GetServices();180 return services.Any(s => s.ServiceName == serviceName);181 }182 183 ///184 /// 卸载服务185 /// 186 /// 路径和文件名187 public static void UnInstallService(string filepath)188 {189 try190 {191 //UnInstall Service 192 var myAssemblyInstaller = new AssemblyInstaller193 {194 UseNewContext = true,195 Path = filepath196 };197 myAssemblyInstaller.Uninstall(null);198 myAssemblyInstaller.Dispose();199 }200 catch (Exception ex)201 {202 throw new Exception("unInstallServiceError/n" + ex.Message);203 }204 }205 }206 }
接下来我们封装控制台的操作方法为了实现循环监听这里用了递归
1 using System; 2 using System.Diagnostics; 3 using System.IO; 4 using System.Linq; 5 6 namespace AutoInstallUtil 7 { 8 class Program 9 {10 static void Main(string[] args)11 {12 try13 {14 ServerAction();15 }16 catch (Exception ex)17 {18 Console.WriteLine("发生错误:{0}", ex.Message);19 }20 21 Console.ReadKey();22 }23 24 ///25 /// 操作26 /// 27 private static void ServerAction()28 {29 Console.WriteLine("请输入:1安装 2卸载");30 var condition = Console.ReadLine();31 var currentPath = Environment.CurrentDirectory;32 var currentFileNameVshost = Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName).ToLower();33 var currentFileName = currentFileNameVshost.Replace(".vshost.exe", ".exe");34 var files =35 Directory.GetFiles(currentPath)36 .Select(o => Path.GetFileName(o).ToLower())37 .ToList()38 .Where(39 o =>40 o != currentFileNameVshost41 && o != currentFileName42 && o.ToLower().EndsWith(".exe")43 && o != "installutil.exe"44 && !o.ToLower().EndsWith(".vshost.exe"))45 .ToList();46 if (files.Count == 0)47 {48 Console.WriteLine("未找到可执行文件,请确认当前目录有需要安装的服务程序");49 }50 else51 {52 Console.WriteLine("找到目录有如下可执行文件,请选择需要安装或卸载的文件序号:");53 }54 int i = 0;55 foreach (var file in files)56 {57 Console.WriteLine("序号:{0} 文件名:{1}", i, file);58 i++;59 }60 var serviceFileIndex = Console.ReadLine();61 var servicePathName = currentPath + "\\" + files[Convert.ToInt32(serviceFileIndex)];62 if (condition == "1")63 {64 SystemServices.InstallService(null, servicePathName);65 }66 else67 {68 SystemServices.UnInstallService(servicePathName);69 }70 Console.WriteLine("**********本次操作完毕**********");71 ServerAction();72 }73 }74 }
到此为止简单的安装程序就写完了,为了醒目我选了个红色的西红柿来做为图标,这样显示些
源码和程序
提取码:piq4