首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> C# 入門

C# 建立 Windows Service 完整教學:從專案建立到安裝、啟動、除錯

     編輯:C# 入門

前言

Windows 服務 (Windows Service) 是在背景長期執行、無使用者介面、可開機自動啟動的應用程式。Visual Studio 提供 **Windows Service 專案範本**,讓 C# 開發者輕鬆建立。本文從零開始,涵蓋專案建立、核心程式碼、安裝程式、命令列安裝/解除安裝、除錯技巧與常見坑點。

步驟 1:建立專案

  1. VS 選單:檔案 → 新增 → 專案
  2. 搜尋「Windows Service」或「Worker Service」(.NET Core 3.1+ 推薦 Worker Service)
  3. 專案名稱:MyWindowsService
.NET Framework 專案產生 ServiceBase 繼承類別;.NET Core Worker Service 使用 BackgroundService,本文以 **傳統 .NET Framework** 為主,最後補充 Worker Service 差異。

步驟 2:核心服務邏輯 (Service1.cs)


using System;
using System.IO;
using System.ServiceProcess;

namespace MyWindowsService
{
    public partial class Service1 : ServiceBase
    {
        private readonly string _logPath = @"D:\Logs\MyService.log";
        private Timer _timer;

        public Service1()
        {
            InitializeComponent();
            // 服務屬性設定 (也可在設計師屬性視窗設定)
            this.ServiceName = "MyCustomService";
            this.CanStop = true;
            this.CanPauseAndContinue = true;
            this.AutoLog = true; // 自動寫入系統事件日誌
        }

        protected override void OnStart(string[] args)
        {
            WriteLog("服務啟動");
            // 範例:每 30 秒執行一次工作
            _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(30));
        }

        protected override void OnStop()
        {
            WriteLog("服務停止");
            _timer?.Dispose();
        }

        protected override void OnPause()
        {
            WriteLog("服務暫停");
            _timer?.Change(Timeout.Infinite, Timeout.Infinite);
        }

        protected override void OnContinue()
        {
            WriteLog("服務繼續");
            _timer?.Change(TimeSpan.Zero, TimeSpan.FromSeconds(30));
        }

        protected override void OnShutdown()
        {
            WriteLog("系統關機,服務關閉");
            _timer?.Dispose();
        }

        private void DoWork(object state)
        {
            try
            {
                WriteLog($"背景工作執行: {DateTime.Now}");
                // 實際業務邏輯:資料庫同步、檔案處理、API 呼叫等
            }
            catch (Exception ex)
            {
                WriteLog($"工作錯誤: {ex}");
                // 可選:EventLog.WriteEntry("MyCustomService", ex.ToString(), EventLogEntryType.Error);
            }
        }

        private void WriteLog(string message)
        {
            try
            {
                Directory.CreateDirectory(Path.GetDirectoryName(_logPath));
                File.AppendAllText(_logPath, $"[{DateTime:yyyy-MM-dd HH:mm:ss}] {message}\r\n");
            }
            catch { /* 忽略日誌錯誤,避免影響主流程 */ }
        }
    }
}

步驟 3:加入安裝程式 (關鍵步驟)

  1. 在 Service1.cs 設計檢視 (雙擊開啟設計師)。
  2. 滑鼠右鍵空白處 → **「加入安裝程式」**。
  3. 專案新增 ProjectInstaller.cs,包含兩個元件:
    • serviceProcessInstaller1 (ServiceProcessInstaller)
    • serviceInstaller1 (ServiceInstaller)
  4. 設定屬性:
元件屬性建議值
serviceProcessInstaller1AccountLocalSystem (最高權限)、NetworkService、User (需帳密)
serviceInstaller1ServiceNameMyCustomService (需與 ServiceBase.ServiceName 一致)
serviceInstaller1DisplayName我的自訂服務 (服務管理員顯示名稱)
serviceInstaller1Description定期同步資料的背景服務
serviceInstaller1StartTypeAutomatic (開機自動)、Manual、Disabled

步驟 4:建置專案

  • 選單:建置 → 建置方案 (或 Ctrl+Shift+B)
  • **切勿按 F5 執行**,Windows Service 無法直接在 VS 中啟動偵錯。
  • 輸出:bin\Debug\MyWindowsService.exe

步驟 5:安裝服務 (命令列)

方法一:InstallUtil.exe (.NET Framework)


# 開啟「Visual Studio 開發人員命令提示字元」 (系統管理員)
cd D:\Projects\MyWindowsService\bin\Debug

# 安裝
installutil MyWindowsService.exe

# 解除安裝
installutil /u MyWindowsService.exe
InstallUtil 版本對應:
.NET 4.x: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe
.NET 2.0: C:\Windows\Microsoft.NET\Framework64\v2.0.50727\InstallUtil.exe

方法二:sc.exe (Windows 內建,無需 .NET)


# 建立服務 (binPath 需完整路徑,含引號)
sc create MyCustomService binPath= "D:\Projects\MyWindowsService\bin\Debug\MyWindowsService.exe" start= auto DisplayName= "我的自訂服務"

# 啟動
sc start MyCustomService

# 停止
sc stop MyCustomService

# 刪除
sc delete MyCustomService

方法三:PowerShell (新版 Windows 推薦)


New-Service -Name "MyCustomService" -BinaryPathName "D:\...\MyWindowsService.exe" -DisplayName "我的自訂服務" -StartupType Automatic
Start-Service "MyCustomService"
Remove-Service "MyCustomService" # 需先停止

步驟 6:服務除錯技巧

方法一:Attach to Process (附加至處理序)

  1. 安裝並啟動服務。
  2. VS 選單:偵錯 → 附加至處理序。
  3. 勾選「顯示所有使用者處理序」,找 MyWindowsService.exe,點擊附加。
  4. 下中斷點正常除錯。

方法二:命令列參數模擬啟動 (方便開發)


static void Main()
{
    if (Environment.UserInteractive) // 偵錯模式:直接在 Console 執行
    {
        var service = new Service1();
        service.OnStart(null); // 手動呼叫
        Console.WriteLine("服務執行中... 按 Enter 停止");
        Console.ReadLine();
        service.OnStop();
    }
    else
    {
        ServiceBase.Run(new ServiceBase[] { new Service1() });
    }
}
  • 直接按 F5 執行,即在主控台模擬服務啟動/停止,極大提升開發效率。

方法三:事件日誌


EventLog.WriteEntry("MyCustomService", "啟動完成", EventLogEntryType.Information);
EventLog.WriteEntry("MyCustomService", ex.ToString(), EventLogEntryType.Error);
  • 「事件檢視器」→「Windows 記錄」→「應用程式」查看。

.NET Core / .NET 5+ Worker Service 差異


// Program.cs
public class Program
{
    public static void Main(string[] args) => CreateHostBuilder(args).Build().Run();

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseWindowsService() // 關鍵:支援 Windows Service 生命週期
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService();
            });
}

// Worker.cs
public class Worker : BackgroundService
{
    private readonly ILogger _logger;
    public Worker(ILogger logger) => _logger = logger;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker 執行: {time}", DateTimeOffset.Now);
            await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
        }
    }
}
  • 發佈:dotnet publish -c Release -r win-x64 --self-contained true
  • 安裝:同 sc create 或 InstallUtil (需 .NET Framework 相容),或使用 dotnet-service 工具。

常見問題與解決

問題原因解決
服務啟動後立即停止OnStart 拋出未處理例外try-catch 包裝 OnStart、寫入事件日誌、Attach to Process 除錯
無法寫入檔案/登錄表LocalSystem 權限不足或路徑錯誤確認路徑存在、使用完整路徑、檢查資料夾權限
安裝失敗 "Access denied"非管理員執行命令列以系統管理員身分開啟 CMD/PowerShell
服務名稱衝突已有同名服務sc delete 移除舊服務、更換 ServiceName
定時器不執行Timer 被 GC 回收將 Timer 宣告為類別欄位,防止被回收

總結

建立 Windows Service 關鍵在於:**繼承 ServiceBase 實作 OnStart/OnStop、加入安裝程式設定 StartType/Account、以管理員身分用 InstallUtil/sc.exe 安裝、用 Attach to Process 或 Console 模擬除錯**。掌握此流程,即可將任何背景作業 (排程同步、訊息佇列消費者、檔案監視、API 輪詢) 封裝為穩定的系統服務。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved