Windows Service(Windows 服務)主要是一種長期執行的應用程式,可以在電腦啟動時自動執行服務,且不會顯示任何UI介面來影響使用者,非常適合背景長期執行功能時使用。
建立專案:使用 Visual Studio 2012 開發工具,從建立專案開始
檔案 -> 新增 -> 專案
在「新增專案」視窗選擇
Visual C# -> Windows 桌面 -> Windows 服務 (也就是所謂的 Windows Service 啦!)
視窗下方四個輸入框,依序輸入:
1. 名稱:MyService1。(輸入我們想要新增的專案名稱,我們使用 MyService1 作為範例)
2. 位置:C:\MacBookPro\Projects\。(預設)
3. 方案:建立新方案。(預設)
4. 方案名稱:MyService1。(預設)
並且勾選「為方案建立目錄」(預設)
接著按下「確定」即可以完成專案建立。
其中,「名稱」也就是未來的「服務名稱」,同一台電腦的服務名稱不可以有重覆。
如果,發現「服務名稱」重覆時,可以在「屬性」視窗中,找到「ServiceName」。(其他的參數用預設的就可以了)
建立專案後會產生預設服務MyService1類別,該類別繼承自System.ServiceProcess.ServiceBase服務基礎類別。
由於此預設服務僅能啟動與停止,因此僅需要複寫OnStart及OnStop()方法即可;
若調整CanPauseAndContinue為true時則表示此服務可被暫停與繼續,所以就有複寫OnPause()及OnContinue()方法的必要。
建立專案後,「方案總管」視窗,這裡可以發現這個「Windows 服務」專案和一般專案視窗有些不同
除了一樣有 Program.cs,還多了一個 Service1.cs
右鍵 Service1.cs 選擇「設計工具檢視」點選後,開啟會看到下面的畫面
視窗裡什麼都沒有,Windows 服務,只需要元件不需要有畫面
這時候,檢查屬性參數列表如下:
直接按「開始」按鈕執行的話會看到跳出錯誤提示視窗,因為它是服務,所以無法直接執行
換句話說,這個「服務」專案需要安裝才可以執行
到這裡還沒有開始寫排程器,還要爲這個服務做一些設定
回到Service1.cs的「設計工具檢視」的視窗中點選右鍵,並點選「加入安裝程式」
這時會多一個ProjectInstaller.cs檔案,在「設計工具檢視」下會有「serviceProessInstaller1」「serviceInstaller1」二個檔案。
2.1 點選 serviceInstaller1,在屬性視窗修改參數
這裡需要做一些設定
DisplayName 就是服務要顯示的名稱
Description 服務描述
ServiceName 服務的唯一名稱
StartType 啓動方式,預設值是Manual (手動)、為了讓服務自動啟動所以改選「Automatic」。
DelayedAutoStart 爲開機之後是否延遲啓動
2.2 點選 serviceProcessInstaller1,在屬性視窗修改參數
設定只要改一個
Account 這裡決定服務的帳號與權限
我們可以設定爲LocalSystem (就是最大權限)
在專案視窗選擇「Service1」檔案雙擊,或是右鍵選「檢視程式碼」,
開啟程式碼視窗後,就可以開始編撰程式了。
點選視窗中的「請按這裡切畫到程式碼檢視」、或右鍵 Service1.cs 選擇「檢視程式碼」,
可以看到程式碼,如下;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace MyProject1
{
public partial class MyService1?: ServiceBase
{
public MyService1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
}
}
只有很簡單的OnStart跟OnStop
3.1 首先撰寫定時器
這裡用到 System.Timers 所以要先引用
using System.Timers;
3.2 定義一個定時器屬性
private Timer MyTimer;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
MyTimer = new Timer();
MyTimer.Elapsed += new ElapsedEventHandler(MyTimer_Elapsed);
MyTimer.Interval = 10 * 1000;
MyTimer.Start();
}
撰寫屬於我們的一個方法程式,
private void MyTimer_Elapsed(object sender, ElapsedEventArgs e)
{
// Do SomeThing...
}
3.3 撰寫一個每一個小時執行一次的事件紀錄日誌的服務程式
在專案視窗選擇「Service1」檔案右鍵選「設計工具檢視」,也就是設計模式,
在「工具箱」視窗,選擇「元件」中的「EventLog」拖曳到設計模式視窗中,
3.4 回到Service1「程式碼」
public Service1()
{
InitializeComponent();
this.AutoLog = false;
if (!System.Diagnostics.EventLog.SourceExists("MySource"))
{
System.Diagnostics.EventLog.CreateEventSource("MySource", "MyLog");
}
eventLog1.Source = "MySource";
}
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("Start Timer.");
MyTimer = new Timer();
MyTimer.Elapsed += new ElapsedEventHandler(MyTimer_Elapsed);
MyTimer.Interval = 60 * 60 * 1000;
MyTimer.Start();
}
private void MyTimer_Elapsed(object sender, ElapsedEventArgs e)
{
eventLog1.WriteEntry("Timer Ticked.");
}
protected override void OnStop()
{
eventLog1.WriteEntry("Stop Timer.");
MyTimer.Stop();
MyTimer = null;
}
4.1 安裝服務執行指令 installutil.exe
官方文件提到安裝服務的時候執行指令 installutil.exe
在命令提示字元輸入:InstallUtil MyService1.exe
解除安裝的時候執行指令:InstallUtil /u MyService1.exe
而「installutil.exe」版本需要配合所使用的 .Net Framework 版本,我們本次開發的範例使用的是 .Net Framework 4.5,所以使用 v4.0.30319
在其所在的資料夾打開後,也會看到這個版本的 installutil.exe 檔案
C:\Windows\Microsoft.NET\Framework\<版本號>
註:如果你是其他的.Net Framework版本,打開相關版本資料也會看到 installutil.exe 檔案。
4.2 安裝權限
在前面服務屬性中,Account = LocalSystem
所以使用「系統管理員執行」。
4.3 安裝指令:
註:Account = LocalSystem,也就是需要管理員權限
@ECHO OFF
net session >nul 2>&1
IF NOT %ERRORLEVEL% EQU 0 (
ECHO ERROR: Please run Bat as Administrator.
PAUSE
EXIT /B 1
)
@SETLOCAL enableextensions
@CD /d "%~dp0"
REM The following directory is for .NET 4
SET DOTNETFX4=%SystemRoot%\Microsoft.NET\Framework\v4.0.30319
SET PATH=%PATH%;%DOTNETFX4%
ECHO Installing MyService1...
ECHO ---------------------------------------------------
InstallUtil /i .\MyService1.exe
ECHO ---------------------------------------------------
ECHO Done.
PAUSE
完成之後可以做安裝,然後做測試
在Install-MyService1.bat按右鍵 -> Run as administrator
打開控制台 -> 系統管理工具 -> 服務
這個列表裡面就會多了一個你的服務
裡面的名稱都跟剛剛打的一樣
那我們剛剛寫的日誌呢?
控制台 -> 系統管理工具 -> 事件檢視器
找到Applications and Services (應用程式及服務記錄檔)
就會多出一個MyLog
裡面就是我們寫的日誌檔
之前在重複若干次的 安裝服務/解除安裝服務 的時候
有遇到EventLog的問題
可以嘗試去登錄編輯器(regedit)刪除以下機碼
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\eventlog\MySource
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\MySource
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\MySource
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\MySource
在執行 解除安裝服務 的程式
參考資料:
http://blog.wahahajk.com/2008/06/cservice.html
http://msdn.microsoft.com/en-us/library/y817hyb6(v=vs.110).aspx
http://gogo1119.pixnet.net/blog/post/27575780-%5Bc%23%5D-windows-service%E5%BB%BA%E7%AB%8B%E7%AF%84%E4%BE%8B
http://www.cnblogs.com/xianspace/archive/2009/04/05/1429835.html
http://stackoverflow.com/questions/3307151/receiving-has-already-been-registered-from-eventlog-createeventsource-ev
http://stackoverflow.com/questions/4824051/problem-installing-windows-service