前言
Windows 服務是運行在后臺的應用程序,可以設置其在系統啟動時自動運行,并在系統運行期間持續運行。這種應用程序沒有用戶界面,也不產生可視輸出。通過服務控制管理器進行終止、暫停、啟動的管理。本文將介紹派生自ServiceBase類的方式創建與部署Windows服務內容。
ServiceBase類
ServiceBase類是服務應用程序定義服務類時將繼承自此類。使用【Windows服務(.NET Framework)】項目模板創建服務應用程序,就會創建繼承自此ServiceBase類的Service1類。實現的任何服務都必須重寫 OnStart 與 OnStop二個方法,可以重寫OnPause和OnContinue二個方法。
1、創建服務應用項目
創建新項目----》選擇【Windows 服務(.NET Framework) 】
配置新項目的項目名稱、存儲目錄和選擇使用的目標框架。示例使用【Fountain.ServiceHost.Worker】為項目名稱和解決方案名稱。
項目創建成功后,我們會看到創建了Service1和Program二個類。可以根據實際需要對Service1類進行重命名。using System.ServiceProcess;
namespace Fountain.ServiceHost.AutoWorker
{
internal static class Program
{
/// <summary>
/// 應用程序的主入口點。
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new ServiceLog()
};
ServiceBase.Run(ServicesToRun);
}
}
}
服務類代碼:在服務類的OnStart和OnStop方法,根據實際業務編寫代碼。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>
/// 構造方法
/// </summary>
public ServiceLog()
{
InitializeComponent();
}
/// <summary>
/// 服務啟動:服務運行時需采取的操作。
/// </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>
/// 服務停止:服務停止運行時需采取的操作。
/// </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>();
//文件數組
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、部署服務應用項目
選擇安裝程序類----》點擊添加。創建安裝程序成功,并自動生成繼承自Installer類的類。示例將安裝類命名為【WinServiceInstaller】
安裝服務類代碼:服務組件中的服務名稱、服務描述等基本信息。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,
//服務名稱
ServiceName = windowsServiceName,
//服務描述
Description = windowsServiceDescription
};
base.Installers.Add(serviceProcessInstaller);
base.Installers.Add(serviceInstaller);
}
catch (Exception objException)
{
throw new Exception(objException.Message);
}
}
}
}
編譯項目程序,部署到Windows服務:使用installutil.exe。#region 示例安裝部署
// 以管理員身份運行cmd命令,把目錄定位到InstallUtil.exe 所在的目錄
// 安裝服務
InstallUtil C:\Project\WinService\WebWorker.exe
// 卸載服務
InstallUtil /u C:\Project\WinService\WebWorker.exe
#endregion
using System;
using System.Configuration.Install;
using System.ServiceProcess;
using System.Windows.Forms;
namespace Fountain.ServiceHost.Main
{
public partial class FormMain : Form
{
/// <summary>
/// 構造方法
/// </summary>
public FormMain()
{
InitializeComponent();
}
/// <summary>
/// 安裝服務
/// </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 + "服務已安載成功");
}
}
catch (Exception exception)
{
if (exception.InnerException != null)
{
MessageBox.Show(exception.InnerException.Message);
}
else
{
MessageBox.Show(exception.Message);
}
}
}
/// <summary>
/// 卸載服務
/// </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 + "服務已卸載成功");
}
}
catch (Exception exception)
{
if (exception.InnerException != null)
{
MessageBox.Show(exception.InnerException.Message);
}
else
{
MessageBox.Show(exception.Message);
}
}
}
/// <summary>
/// 獲得服務的對象
/// </summary>
/// <param name="servicename">服務名稱</param>
/// <returns>ServiceController對象,若沒有該服務,則返回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);
}
}
}
}
示例完整代碼:
小結
以上是C#使用ServiceBase類創建與部署服務應用程序的全部內容,是.NET Framework 提供的一種實現方式。而NET Core 3.0 及以上和.NET 6.0還提供了另一種實現方式,后續介紹。希望本文對有需要的朋友能提供一些參考。如有不到之處,請多多包涵。
該文章在 2024/6/8 18:06:30 編輯過