前言
Windows 服務(wù)是運(yùn)行在后臺的應(yīng)用程序,可以設(shè)置其在系統(tǒng)啟動時自動運(yùn)行,并在系統(tǒng)運(yùn)行期間持續(xù)運(yùn)行。這種應(yīng)用程序沒有用戶界面,也不產(chǎn)生可視輸出。通過服務(wù)控制管理器進(jìn)行終止、暫停、啟動的管理。本文將介紹派生自ServiceBase類的方式創(chuàng)建與部署Windows服務(wù)內(nèi)容。
ServiceBase類
ServiceBase類是服務(wù)應(yīng)用程序定義服務(wù)類時將繼承自此類。使用【W(wǎng)indows服務(wù)(.NET Framework)】項(xiàng)目模板創(chuàng)建服務(wù)應(yīng)用程序,就會創(chuàng)建繼承自此ServiceBase類的Service1類。實(shí)現(xiàn)的任何服務(wù)都必須重寫 OnStart 與 OnStop二個方法,可以重寫OnPause和OnContinue二個方法。
1、創(chuàng)建服務(wù)應(yīng)用項(xiàng)目
創(chuàng)建新項(xiàng)目----》選擇【W(wǎng)indows 服務(wù)(.NET Framework) 】
配置新項(xiàng)目的項(xiàng)目名稱、存儲目錄和選擇使用的目標(biāo)框架。示例使用【Fountain.ServiceHost.Worker】為項(xiàng)目名稱和解決方案名稱。
項(xiàng)目創(chuàng)建成功后,我們會看到創(chuàng)建了Service1和Program二個類。可以根據(jù)實(shí)際需要對Service1類進(jìn)行重命名。using System.ServiceProcess;
namespace Fountain.ServiceHost.AutoWorker
{
internal static class Program
{
/// <summary>
/// 應(yīng)用程序的主入口點(diǎn)。
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new ServiceLog()
};
ServiceBase.Run(ServicesToRun);
}
}
}
服務(wù)類代碼:在服務(wù)類的OnStart和OnStop方法,根據(jù)實(shí)際業(yè)務(wù)編寫代碼。using System;
using System.Collections.Generic;
using System.IO;
using System.ServiceProcess;
using System.Threading;
namespace Fountain.ServiceHost.AutoWorker
{
public partial class ServiceLog : ServiceBase
{
// 刪除日志計時器
private System.Threading.Timer deleteTimer;
/// <summary>
/// 構(gòu)造方法
/// </summary>
public ServiceLog()
{
InitializeComponent();
}
/// <summary>
/// 服務(wù)啟動:服務(wù)運(yùn)行時需采取的操作。
/// </summary>
/// <param name="args"></param>
protected override void OnStart(string[] args)
{
TimerCallback deleteTimerCallback = new TimerCallback(Delete);
//
this.deleteTimer = new System.Threading.Timer(deleteTimerCallback, 30, 5000, 60000);
}
/// <summary>
/// 服務(wù)停止:服務(wù)停止運(yùn)行時需采取的操作。
/// </summary>
protected override void OnStop()
{
this.deleteTimer?.Dispose();
}
/// <summary>
/// 刪除日志文件
/// </summary>
/// <param name="retentionDays">保留幾天的日志文件</param>
public void Delete(object retentionDays)
{
try
{
List<string> retentionFiles = new List<string>();
//文件數(shù)組
string[] keepfile = new string[Convert.ToInt32(retentionDays)];
for (int i = 0; i < Convert.ToInt32(retentionDays); i++)
{
retentionFiles.Add(string.Format("{0:yyyyMMdd}", DateTime.Now.AddDays(-(i))));
}
DirectoryInfo directoryInfo= new DirectoryInfo($"{AppDomain.CurrentDomain.BaseDirectory}{Path.DirectorySeparatorChar}log");
//目錄是否存在
if (directoryInfo.Exists)
{
foreach (FileInfo fileInfo in directoryInfo.GetFiles())
{
if (retentionFiles.Contains(fileInfo.Name))
{
continue;
}
fileInfo.Delete();
}
}
}
catch
{
}
}
}
}
2、部署服務(wù)應(yīng)用項(xiàng)目
右擊項(xiàng)目----》選擇添加----》類
選擇安裝程序類----》點(diǎn)擊添加。創(chuàng)建安裝程序成功,并自動生成繼承自Installer類的類。示例將安裝類命名為【W(wǎng)inServiceInstaller】
安裝服務(wù)類代碼:服務(wù)組件中的服務(wù)名稱、服務(wù)描述等基本信息。using System;
using System.ComponentModel;
using System.ServiceProcess;
namespace Fountain.ServiceHost.Worker
{
[RunInstaller(true)]
public partial class WinServiceInstaller : System.Configuration.Install.Installer
{
private readonly ServiceProcessInstaller serviceProcessInstaller;
private readonly ServiceInstaller serviceInstaller;
public WinServiceInstaller()
{
try
{
string windowsServiceName = "ClearLogFile";
string windowsServiceDescription = "清理日志歷史文件";
serviceProcessInstaller = new ServiceProcessInstaller
{
//賬戶類型
Account = ServiceAccount.LocalSystem
};
serviceInstaller = new ServiceInstaller
{
StartType = ServiceStartMode.Automatic,
//服務(wù)名稱
ServiceName = windowsServiceName,
//服務(wù)描述
Description = windowsServiceDescription
};
base.Installers.Add(serviceProcessInstaller);
base.Installers.Add(serviceInstaller);
}
catch (Exception objException)
{
throw new Exception(objException.Message);
}
}
}
}
編譯項(xiàng)目程序,部署到Windows服務(wù):使用installutil.exe。#region 示例安裝部署
// 以管理員身份運(yùn)行cmd命令,把目錄定位到InstallUtil.exe 所在的目錄
// 安裝服務(wù)
InstallUtil C:\Project\WinService\WebWorker.exe
// 卸載服務(wù)
InstallUtil /u C:\Project\WinService\WebWorker.exe
#endregion
也可編寫一個界面程序進(jìn)行安裝與卸載服務(wù)。using System;
using System.Configuration.Install;
using System.ServiceProcess;
using System.Windows.Forms;
namespace Fountain.ServiceHost.Main
{
public partial class FormMain : Form
{
/// <summary>
/// 構(gòu)造方法
/// </summary>
public FormMain()
{
InitializeComponent();
}
/// <summary>
/// 安裝服務(wù)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonInstall_Click(object sender, EventArgs e)
{
try
{
if (this.GetService(this.textBoxServiceName.Text) == null)
{
string servicepath = AppDomain.CurrentDomain.BaseDirectory + @"AutoWorker.exe";
ManagedInstallerClass.InstallHelper(new string[] { servicepath });
MessageBox.Show(this.textBoxServiceName.Text + "服務(wù)已安載成功");
}
}
catch (Exception exception)
{
if (exception.InnerException != null)
{
MessageBox.Show(exception.InnerException.Message);
}
else
{
MessageBox.Show(exception.Message);
}
}
}
/// <summary>
/// 卸載服務(wù)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonUnInstall_Click(object sender, EventArgs e)
{
try
{
if (this.GetService(this.textBoxServiceName.Text) != null)
{
string servicepath = AppDomain.CurrentDomain.BaseDirectory + @"AutoWorker.exe";
ManagedInstallerClass.InstallHelper(new string[] { "/u", servicepath });
MessageBox.Show(this.textBoxServiceName.Text + "服務(wù)已卸載成功");
}
}
catch (Exception exception)
{
if (exception.InnerException != null)
{
MessageBox.Show(exception.InnerException.Message);
}
else
{
MessageBox.Show(exception.Message);
}
}
}
/// <summary>
/// 獲得服務(wù)的對象
/// </summary>
/// <param name="servicename">服務(wù)名稱</param>
/// <returns>ServiceController對象,若沒有該服務(wù),則返回null</returns>
public ServiceController GetService(string servicename)
{
try
{
ServiceController[] serviceController = ServiceController.GetServices();
foreach (ServiceController serviceItem in serviceController)
{
if (serviceItem.ServiceName.Equals(servicename, StringComparison.OrdinalIgnoreCase))
{
return serviceItem;
}
}
return null;
}
catch (Exception exception)
{
throw new Exception(exception.Message);
}
}
}
}
示例完整代碼:
小結(jié)
以上是C#使用ServiceBase類創(chuàng)建與部署服務(wù)應(yīng)用程序的全部內(nèi)容,是.NET Framework 提供的一種實(shí)現(xiàn)方式。而NET Core 3.0 及以上和.NET 6.0還提供了另一種實(shí)現(xiàn)方式,后續(xù)介紹。希望本文對有需要的朋友能提供一些參考。如有不到之處,請多多包涵。
該文章在 2024/6/8 18:06:30 編輯過