星期一, 11月 28, 2016

[C#] Windows Service

根據這篇 MSDN 文章 逐步解說:在元件設計工具中建立 Windows 服務應用程式 的筆記,該文章是利用 Windows Service 的啟動、停止和 Timer 來對事件檢視器新增資料,藉此觀察 Windows Service 狀態

在 VS 2015 上建立 Windows Service 範本,路徑是 [Visucal C# => 傳統桌面 => Windows 服務],一開始要找到該範本就卡關,利用 "Windows Service" 去搜尋,完全找不到,以為要在 VS 上另外安裝,Google 後才恍然大悟,中文版應該用 "Windows 服務" 去找才對啦,Orz

[C#] Windows Service-6


在服務中加入功能

Windows 服務範本建立後,會有一個 Service1.cs,更名為 MyNewService.cs,該 Class 會繼承 ServiceBase,相關設定和 Code 如下
  1. 建構子內對事件檢視器建立專屬事件
  2. 服務啟動、結束時,會對事件檢視器插入資料
  3. 建立 Timer,定時對事件檢視器插入資料
開啟 MyNewService.cs 檔案

[C#] Windows Service-7
// EventLog 所在 Namespace
using System.Diagnostics;
// Timer 所在 Namespace
using System.Timers;

namespace WalkthroughWindowsService
{
    // 繼承 System.ServiceProcess.ServiceBase
    public partial class MyNewService : ServiceBase
    {
        private EventLog eventLog1;
        private Timer timer;
        // 紀錄 Timer 觸發幾次
        private int eventId = 1;

        public MyNewService()
        {
            InitializeComponent();

            eventLog1 = new EventLog();
            if (!EventLog.SourceExists("MySource"))
                EventLog.CreateEventSource("MySource", "MyNewLog");

            eventLog1.Source = "MySource";
            eventLog1.Log = "MyNewLog";
        }

        protected override void OnStart(string[] args)
        {
            eventLog1.WriteEntry("Windows Service 啟動");

            timer = new Timer();
            // 1 分鐘 (60 秒) 觸發一次
            timer.Interval = 60000;
            timer.Elapsed += (sender, e) =>
            {
                // 利用事件識別碼來記錄 Timer 觸發幾次
                eventLog1.WriteEntry("Timer 觸發", EventLogEntryType.Information, eventId++);
            };
            timer.Start();
        }

        protected override void OnStop()
        {
            eventLog1.WriteEntry("Windows Service 停止");
            timer.Stop();
            timer = null;
        }
    }
}
將安裝程式加入服務

在 MyNewService.cs 設計介面上,滑鼠右鍵並選擇"加入安裝程式"

[C#] Windows Service-2

加入安裝程式後,在 Project 內會加入 ProjectInstaller.cs 檔案,打開後會有 ServiceProcessInstaller 和 ServiceInstaller 這兩個元件類別

[C#] Windows Service-3

ServiceInstaller.cs 屬性設定
  • ServiceName:MyNewService
  • Description:會出現在 [服務] 視窗中,並協助使用者識別服務,以及了解它的用途。
  • DisplayName:會出現在 [服務] 視窗的 [名稱] 欄中的文字,假如是要在 cmd 上透過 net start 和 net stop 來啟動、停止服務的話,也是輸入 DisplayName,而非 ServiceName 喔
  • StartType:預設是 Manual,更改為 Automatic
[C#] Windows Service-4

ServiceProcessInstaller 屬性設定
  • Account:預設為 User,更改為 LocalSystem,只有 LocalSystem 才有寫入事件器權限
  • MSDN 文章內的安全提示
  • LocalSystem 帳戶具有概括性的使用權限,包括寫入事件記錄檔的能力。 因此,請謹慎使用這個帳戶,因為它會增加您遭受惡意軟體攻擊的風險。 至於其他工作,建議使用 LocalService 帳戶,可在本機電腦上做為沒有權限的使用者,並提供匿名認證給任何遠端伺服器。 如果您嘗試使用 LocalService 帳戶,因為需要寫入事件記錄檔的權限,所以這個範例會失敗。
[C#] Windows Service-5

該 Project 進行到此的情況

[C#] Windows Service-1

安裝服務

利用 administrator 權限,在 cmd 中使用 installutil.exe 來安裝 WalkthroughWindowsService.exe
InstallUtil.exe 是透過 .NET Framework 安裝至資料夾 %WINDIR%\Microsoft.NET\Framework[64]\framework_version。 例如,32 位元版本的 .NET Framework 4、4.5、4.5.1 和 4.5.2 的預設路徑是 C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe
[C#] Windows Service-8

安裝語法
C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe D:\Dropbox\C#\Practice\WalkthroughWindowsService\WalkthroughWindowsService\bin\Debug\WalkthroughWindowsService.exe
[C#] Windows Service-9

解除語法
C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe /u D:\Dropbox\C#\Practice\WalkthroughWindowsService\WalkthroughWindowsService\bin\Debug\WalkthroughWindowsService.exe
[C#] Windows Service-12

安裝與解除,只差異在 /u 參數

啟動服務

在服務內透過 UI 操作來啟動、停止 Windows Service

[C#] Windows Service-10

cmd 內利用 net start 和 net stop 來啟動、停止 Windows Service,是利用 DisplayName 而非 ServiceName

[C#] Windows Service-11

測試 Windows Service 執行狀態

[C#] Windows Service-13

沒有留言:

張貼留言