Windows服务安装与控制
1、建立服务
(1)定义一个ServiceInstaller
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace WindowService { [System.ComponentModel.RunInstaller(true)] public class ServiceInstaller : System.Configuration.Install.Installer { System.ServiceProcess.ServiceProcessInstaller processInstaller; System.ServiceProcess.ServiceInstaller serviceInstaller; public ServiceInstaller() { processInstaller = new System.ServiceProcess.ServiceProcessInstaller(); processInstaller.Account = System.ServiceProcess.ServiceAccount.LocalSystem; Installers.Add(processInstaller); serviceInstaller = new System.ServiceProcess.ServiceInstaller(); serviceInstaller.DisplayName = "000000000"; serviceInstaller.ServiceName = "000000000"; serviceInstaller.StartType = System.ServiceProcess.ServiceStartMode.Automatic; Installers.Add(serviceInstaller); } protected override void OnAfterInstall(System.Collections.IDictionary savedState) { base.OnAfterInstall(savedState); } } }
(2)定义一个服务
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Linq; using System.ServiceProcess; using System.Text; namespace WindowService { partial class Service : ServiceBase { public Service() { InitializeComponent(); } protected override void OnStart(string[] args) { // TODO: 在此处添加代码以启动服务。 } protected override void OnStop() { // TODO: 在此处添加代码以执行停止服务所需的关闭操作。 } } }
(3)定义自己的安装方式:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; namespace WindowService { public class ServiceMaster { static string appPath = Assembly.GetExecutingAssembly().Location; public static void Main(string[] args) { if (args != null && args.Length > 0) { if (args[0] == "-i") { InstallService(); } else if (args[0] == "-u") { UninstallService(); } } else { var s = new Service() { ServiceName = "aaaaa" }; Service.Run(s); } } public static void InstallService() { System.Configuration.Install.ManagedInstallerClass.InstallHelper(new string[] { appPath }); } public static void UninstallService() { System.Configuration.Install.ManagedInstallerClass.InstallHelper(new string[] { "-u", appPath }); } } }
安装时,使用管理员权限运行cmd,输入程序带参数"-i"执行即可安装。这是使用的ManagedInstallerClass类的安装。接下来对上面这个服务使用另一种安装方式。
2、Windows Api安装方式。
(1)辅助类的设计
using System; using System.ComponentModel; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Text; using System.Threading; namespace Yihe.Service { #region 异常定义 /// <summary> /// 服务不存在异常 /// </summary> public class ServiceNotExistException : ApplicationException { public ServiceNotExistException() : base("服务不存在!") { } public ServiceNotExistException(string message) : base(message) { } } #endregion #region 枚举定义 /// <summary> /// 服务启动类型 /// </summary> public enum ServiceStartType { Boot, System, Auto, Manual, Disabled } /// <summary> /// 服务运行帐户 /// </summary> public enum ServiceAccount { LocalSystem, LocalService, NetworkService, } #endregion /// <summary> /// Windows 服务辅助类 /// </summary> public static class ServiceHelper { #region 公开方法 /// <summary> /// 安装服务 /// </summary> /// <param name="serviceName">服务名</param> /// <param name="displayName">友好名称</param> /// <param name="binaryFilePath">映像文件路径,可带参数</param> /// <param name="description">服务描述</param> /// <param name="startType">启动类型</param> /// <param name="account">启动账户</param> /// <param name="dependencies">依赖服务</param> public static void Install(string serviceName, string displayName, string binaryFilePath, string description, ServiceStartType startType, ServiceAccount account = ServiceAccount.LocalSystem, string[] dependencies = null) { IntPtr scm = OpenSCManager(); IntPtr service = IntPtr.Zero; try { service = Win32Class.CreateService(scm, serviceName, displayName, Win32Class.SERVICE_ALL_ACCESS, Win32Class.SERVICE_WIN32_OWN_PROCESS, startType, Win32Class.SERVICE_ERROR_NORMAL, binaryFilePath, null, IntPtr.Zero, ProcessDependencies(dependencies), GetServiceAccountName(account), null); if (service == IntPtr.Zero) { if (Marshal.GetLastWin32Error() == 0x431)//ERROR_SERVICE_EXISTS { throw new ApplicationException("服务已存在!"); } throw new ApplicationException("服务安装失败!"); } //设置服务描述 Win32Class.SERVICE_DESCRIPTION sd = new Win32Class.SERVICE_DESCRIPTION(); try { sd.description = Marshal.StringToHGlobalUni(description); Win32Class.ChangeServiceConfig2(service, 1, ref sd); } finally { Marshal.FreeHGlobal(sd.description); //释放 } } finally { if (service != IntPtr.Zero) { Win32Class.CloseServiceHandle(service); } Win32Class.CloseServiceHandle(scm); } } /// <summary> /// 卸载服务 /// </summary> /// <param name="serviceName">服务名</param> public static void Uninstall(string serviceName) { IntPtr scmHandle = IntPtr.Zero; IntPtr service = IntPtr.Zero; try { service = OpenService(serviceName, out scmHandle); StopService(service); //停止服务。里面会递归停止从属服务 if (!Win32Class.DeleteService(service) && Marshal.GetLastWin32Error() != 0x430) //忽略已标记为删除的服务。ERROR_SERVICE_MARKED_FOR_DELETE { throw new ApplicationException("删除服务失败!"); } } catch (ServiceNotExistException) { } //忽略服务不存在的情况 finally { if (service != IntPtr.Zero) { Win32Class.CloseServiceHandle(service); Win32Class.CloseServiceHandle(scmHandle);//放if里面是因为如果服务打开失败,在OpenService里就已释放SCM } } } #endregion #region 辅助方法 /// <summary> /// 转换帐户枚举为有效参数 /// </summary> public static string GetServiceAccountName(ServiceAccount account) { if (account == ServiceAccount.LocalService) { return @"NT AUTHORITYLocalService"; } if (account == ServiceAccount.NetworkService) { return @"NT AUTHORITYNetworkService"; } return null; } /// <summary> /// 处理依赖服务参数 /// </summary> public static string ProcessDependencies(string[] dependencies) { if (dependencies == null || dependencies.Length == 0) { return null; } StringBuilder sb = new StringBuilder(); foreach (string s in dependencies) { sb.Append(s).Append('