1. 介绍
过去称为 NT 服务,允许用户创建可在其自身的 Windows 会话中长时间运行的可执行应用程序。 这些服务可在计算机启动时自动启动,可以暂停和重启,并且不显示任何用户界面。
2. 创建 Windows 服务应用
2.1 创建服务并给服务重命名
开发环境:Windows10操作系统 + vs2015开发环境
在“解决方案资源管理器”中,从“MyNewService.cs”或“MyNewService.vb”的快捷菜单中,选择“查看设计器”。
在“工具箱”中,展开“组件”,然后将“EventLog”组件拖到“Service1.cs [Design]”或“Service1.vb [Design]”标签。
在“解决方案资源管理器”中,选择“Service1.cs”或“Service1.vb”,然后从快捷菜单中选择“重命名”。 将文件重命名为“MyNewService.cs”或“MyNewService.vb”
2.2 向服务添加功能
在MyNewService设计器,右击
注意:
LocalSystem 帐户具有广泛的权限,包括能够写入事件日志。
使用此帐户时要特别小心,因为它会增加你受到恶意软件攻击的风险。
对于其他任务,请考虑使用 LocalService 帐户,该帐户用作本地计算机上的非特权用户,并向任意远程服务器提供匿名凭据。
如果你尝试使用 LocalService 账户,此例子将失败,因为它需要写入事件日志的权限。
namespace MyNewService
{
public partial class MyNewService : ServiceBase
{
// 写入事件日志的事件的标识符
private int eventId = 1;
#region /* 设置服务状态 */
// 使用平台调用声明 SetServiceStatus 函数
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool SetServiceStatus(System.IntPtr handle, ref ServiceStatus serviceStatus);
// 声明 ServiceState 值和添加你将在平台调用中使用的状态结构
public enum ServiceState
{
SERVICE_STOPPED = 0x00000001,
SERVICE_START_PENDING = 0x00000002,
SERVICE_STOP_PENDING = 0x00000003,
SERVICE_RUNNING = 0x00000004,
SERVICE_CONTINUE_PENDING = 0x00000005,
SERVICE_PAUSE_PENDING = 0x00000006,
SERVICE_PAUSED = 0x00000007,
}
[StructLayout(LayoutKind.Sequential)]
public struct ServiceStatus
{
public int dwServiceType;
public ServiceState dwCurrentState;
public int dwControlsAccepted;
public int dwWin32ExitCode;
public int dwServiceSpecificExitCode;
public int dwCheckPoint;
public int dwWaitHint;
};
#endregion
public MyNewService()
{
InitializeComponent();
//添加自定义事件日志功能 到 Windows 服务——“事件查看器”中找到MyNewLog
eventLog1 = new System.Diagnostics.EventLog();
if (!System.Diagnostics.EventLog.SourceExists("MySource"))
{
System.Diagnostics.EventLog.CreateEventSource(
"MySource", "MyNewLog");
}
eventLog1.Source = "MySource";
eventLog1.Log = "MyNewLog";
}
/// <summary>
/// 根据用户提供的启动参数设置事件源和日志名称。 如果未提供参数,则使用默认值。
/// </summary>
/// <param name="args"></param>
public MyNewService(string[] args)
{
InitializeComponent();
string eventSourceName = "MySource";
string logName = "MyNewLog";
if (args.Length > 0)
{
eventSourceName = args[0];
}
if (args.Length > 1)
{
logName = args[1];
}
eventLog1 = new EventLog();
if (!EventLog.SourceExists(eventSourceName))
{
EventLog.CreateEventSource(eventSourceName, logName);
}
eventLog1.Source = eventSourceName;
eventLog1.Log = logName;
}
protected override void OnStart(string[] args)
{
// 将服务状态更新为“开始挂起”。
ServiceStatus serviceStatus = new ServiceStatus();
serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING;
serviceStatus.dwWaitHint = 100000;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
// 在服务启动时向事件日志写入一个条目
eventLog1.WriteEntry("In OnStart.");
//# 在服务操作开始后,OnStart 方法必须返回操作系统,以便不阻止系统。
// 所以若要设置简单的轮询机制,设置一个每分钟触发一次的Timer计时器,以此可以进行监视服务。
//# 当然也可以使用后台工作线程来运行任务,进行轮询。
Timer timer = new Timer();
timer.Interval = 60000; // 60 seconds
timer.Elapsed += new ElapsedEventHandler(this.OnTimer);
timer.Start();
// 将服务状态更新为正在运行。
serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
}
public void OnTimer(object sender, ElapsedEventArgs args)
{
// TODO:在此处插入监控活动。
eventLog1.WriteEntry("Monitoring the System", EventLogEntryType.Information, eventId++);
}
protected override void OnStop()
{
// 将服务状态更新为“停止挂起”。
ServiceStatus serviceStatus = new ServiceStatus();
serviceStatus.dwCurrentState = ServiceState.SERVICE_STOP_PENDING;
serviceStatus.dwWaitHint = 100000;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
// 在服务停止时向事件日志添加一个条目
eventLog1.WriteEntry("In OnStop.");
// 将服务状态更新为已停止。
serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
}
/// <summary>
/// 定义服务的OnContinue操作
/// </summary>
protected override void OnContinue()
{
eventLog1.WriteEntry("In OnContinue.");
}
/// <summary>
/// 定义服务的OnPause操作
/// </summary>
protected override void OnPause()
{
eventLog1.WriteEntry("In OnPause.");
}
/// <summary>
/// 定义服务的OnShutdown操作
/// </summary>
protected override void OnShutdown()
{
eventLog1.WriteEntry("In OnShutdown .");
}
}
}
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
static void Main(string[] args)
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyNewService(args)
};
ServiceBase.Run(ServicesToRun);
}
}
namespace MyNewService
{
[RunInstaller(true)]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{
public ProjectInstaller()
{
InitializeComponent();
}
private void serviceProcessInstaller1_AfterInstall(object sender, InstallEventArgs e)
{
}
protected override void OnBeforeInstall(IDictionary savedState)
{
string parameter = "MySource1\" \"MyLogFile1";
Context.Parameters["assemblypath"] = "\"" + Context.Parameters["assemblypath"] + "\" \"" + parameter + "\"";
base.OnBeforeInstall(savedState);
}
}
}
2.3 生成服务
生成解决方法
2.4 安装服务
要安装 Windows 服务,必须在安装它的计算机上拥有管理员凭据。进入“Visual Studio 的开发人员命令提示”窗口,导航到包含项目输出的文件夹(默认情况下,它是项目的 \bin\Debug 子目录),输入命令:
installutil MyNewService.exe
2.5 启动并运行服务
2.5.1 在 Windows 中,打开“服务”桌面应用程序
按“Windows 徽标键+R”以打开“运行”框,然后输入 services.msc 并按 Enter 或单击“确定”。
若要启动该服务,请从服务的快捷菜单中选择“启动”。
若要停止该服务,请从服务的快捷菜单中选择“停止”。
(可选)可在命令行使用“net start<服务名称>”和“net stop<服务名称>”来启动和停止服务。
2.5.2 在 Windows 中,打开“事件查看器”桌面应用
在 Windows 搜索栏中输入事件查看器,然后从搜索结果中选择“事件查看器”。
2.6 卸载服务
使用管理员凭据,进入“Visual Studio 的开发人员命令提示”窗口,导航到包含项目输出的文件夹(默认情况下,它是项目的 \bin\Debug 子目录),输入命令:
installutil.exe /u MyNewService.exe
参考文章:
(1)开发 Windows 服务应用:https://docs.microsoft.com/zh-cn/dotnet/framework/windows-services/
(2)vs2015开发Windows服务:http://www.cnblogs.com/xujie/p/5695673.html