一、概述
Windows service即Microsoft Windows服务,基于.net framework平台开发,只能运行在Windows操作系统中。这些服务可以在计算机启动时自动启动,可以暂停和重新启动,并且不显示任何用户界面。这些功能使服务非常适合在服务器上使用,或者在需要长期运行的功能而又不会干扰在同一台计算机上工作的其他用户的情况下使用。还可以在与登录用户或默认计算机帐户不同的特定用户帐户的安全上下文中运行服务。
二、示例
1、开发环境
操作系统:Windows10 X64
开发环境:VS2019
编程语言:C#
.NET版本:.NET Framework 4.7.2
目标平台:Any CUP
2、创建Windows Service
新建一个Windows Service,并将项目名称改为“WindowsService1”,如下图所示:
进入“Service1”设计界面,在空白位置右击鼠标弹出上下文菜单,选中“添加安装程序”,如下图所示:
此时软件会生成两个组件,分别为“serviceInstaller1”及“serviceProcessInstaller1”,ServiceProcessInstaller 类和 ServiceInstaller 类用于安装和配置服务程序。如下图所示:
设置“serviceInstaller1”及“serviceProcessInstaller1”的属性
可以在sevice1中加入需要执行的逻辑
至此,Windows服务已经创建完毕。
三、安装、启动、停止、卸载服务的方式
1、方式一
通过InstallUtil.exe安装、卸载、启动、停止Windows Service。
- 以管理员身份运行cmd
- 安装windows服务
cd C:WindowsMicrosoft.NETFrameworkv4.0.30319 (InstallUtil.exe的路径下,注意InstallUtil.exe的版本号需要和项目的版本号相同)
InstallUtil.exe D:PersonalInfowindowsservicesWindowsService1WindowsService1inDebugWindowsService1.exe(项目的路径)
-----------------------------注意-------------------------------
安装过程中有可能需要输入用户名和密码,这个和ServiceProcessInstaller 类的Account属性有关。
- 启动windows服务
net start Service1(服务名称)
- 停止Windows服务
net stop service1(服务名称)
- 卸载windows服务
InstallUtil.exe /u D:PersonalInfowindowsservicesWindowsService1WindowsService1inDebugWindowsService1.exe
2、方法二
- 找到 Installutil.exe 文件,并把它复制到 D:PersonalInfowindowsservicesWindowsService1WindowsService1inDebug目录
- 现在 Installutil.exe 程序在 D:PersonalInfowindowsservicesWindowsService1WindowsService1inDebug目录下,需要通过cmd命令 "cd" 切换到该目录下。
- 安装服务
installutil.exe WindowsService1.exe
- 启动服务
net start service1
- 停止服务
net stop service1
- 卸载服务
installutil.exe /u WindowsService1.exe
3、方式三
通过操作控制台来统一管理。主要使用System.ServiceProcess及System.Configuration.Install实现。
- 在同一个解决方案里新建一个wpf项目,并命名为WpfApp1,如下图所示:
- 将该项目设置为启动项目,并添加四个按钮,分别为安装服务、启动服务、停止服务及卸载服务,如下图所示:
- 按下F7进入代码编辑界面,引用“System.ServiceProcess”及“System.Configuration.Install”,并输入如下代码:
using System; using System.Collections; using System.Configuration.Install; using System.ServiceProcess; using System.Windows; namespace WpfApp1 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } string serviceFilePath = $"{AppDomain.CurrentDomain.BaseDirectory}WindowsService1.exe"; string serviceName = "Service1"; /// <summary> /// 关闭服务 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Stop_Click(object sender, RoutedEventArgs e) { if (this.IsServiceExisted(serviceName)) { this.ServiceStop(serviceName); } } /// <summary> /// 启动服务 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Start_Click(object sender, RoutedEventArgs e) { if (this.IsServiceExisted(serviceName)) { this.ServiceStart(serviceName); } } /// <summary> /// 安装服务 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Install_Click(object sender, RoutedEventArgs e) { if (this.IsServiceExisted(serviceName)) { this.UninstallService(serviceFilePath); } this.InstallService(serviceFilePath); } /// <summary> /// 卸载服务 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Uninstall_Click(object sender, RoutedEventArgs e) { if (this.IsServiceExisted(serviceName)) { this.ServiceStop(serviceName); this.UninstallService(serviceFilePath); } } #region 私有方法 /// <summary> /// 判断服务是否存在 /// </summary> /// <param name="serviceName"></param> /// <returns></returns> private bool IsServiceExisted(string serviceName) { ServiceController[] services = ServiceController.GetServices(); foreach (ServiceController sc in services) { if (sc.ServiceName.ToLower() == serviceName.ToLower()) { return true; } } return false; } /// <summary> /// 卸载服务 /// </summary> /// <param name="serviceFilePath"></param> private void UninstallService(string serviceFilePath) { using (AssemblyInstaller installer = new AssemblyInstaller()) { installer.UseNewContext = true; installer.Path = serviceFilePath; installer.Uninstall(null); } } /// <summary> /// 安装服务 /// </summary> /// <param name="serviceFilePath"></param> private void InstallService(string serviceFilePath) { using (AssemblyInstaller installer = new AssemblyInstaller()) { installer.UseNewContext = true; installer.Path = serviceFilePath; IDictionary savedState = new Hashtable(); installer.Install(savedState); installer.Commit(savedState); } } /// <summary> /// 启动服务 /// </summary> /// <param name="serviceName"></param> private void ServiceStart(string serviceName) { using (ServiceController control = new ServiceController(serviceName)) { if (control.Status == ServiceControllerStatus.Stopped) { control.Start(); } } } /// <summary> /// 停止服务 /// </summary> /// <param name="serviceName"></param> private void ServiceStop(string serviceName) { using (ServiceController control = new ServiceController(serviceName)) { if (control.Status == ServiceControllerStatus.Running) { control.Stop(); } } } #endregion } }
- 为了后续调试服务及安装卸载服务的需要,将已生成的MyWindowsService.exe引用到本wpf项目中,如下图所示:
- 由于需要安装服务,故需要使用UAC中Administrator的权限,鼠标右击项目“WpfApp1”,在弹出的上下文菜单中选择“添加”->“新建项”,在弹出的选择窗体中选择“应用程序清单文件”并单击确定,如下图所示:
- 打开该文件,并将<requestedExecutionLevel level="asInvoker" uiAccess="false" />改为<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />,如下图所示:
4、方式四
通过SC命令安装、卸载、启动、停止Windows Service。
- 安装Windows service
sc create service1 binPath= "D:PersonalInfowindowsservicesWindowsService1WindowsService1inDebugWindowsService1.exe"
其中:service1 为创建的服务名,binPath后面是运行exe文件的所在路径
- 配置服务
sc config service1 start= AUTO (自动) sc config service1 start= DEMAND (手动) sc config service1 start= DISABLED(禁用)
其中service1是创建的服务名
- 开启服务
net start service1
其中service1是创建的服务名
- 关闭服务
net stop service1
其中service1是创建的服务名
- 删除服务
sc delete service1
其中service1是创建的服务名
5、方式五-批处理
新建一个txt文件,自己命名,把后缀改为.bat文件
- 创建、配置、开启服务
@echo.服务启动...... @echo off @sc create test1 binPath= "D:PersonalInfowindowsservicesWindowsService1WindowsService1inDebugWindowsService1.exe" @net start test1 @sc config test1 start= AUTO @echo off @echo.启动完毕! @pause
- 关闭服务
@echo.服务关闭 @echo off @net stop test1 @echo off @echo.关闭结束! @pause
- 删除服务
@echo.服务删除 @echo off @sc delete test1 @echo off @echo.删除结束! @pause