文章大部分內容轉自:http://www.cnblogs.com/greatandforever/archive/2008/10/14/1310504.html;和:http://www.cnblogs.com/xujie/p/5695673.html;部分是我自己后來的一些理解添加進去的。
正文:在網上看了一些示例,大部分都言過其實,把過程搞得太過復雜,老是需要去研究如何利用InstallUtil.exe及其參數。事實上,既然要安裝.net下制作的windows服務,肯定首先得在目標機器上安裝有.net框架。因此,InstallUtil.exe也一定已經存在目標機器上了,因而利用微軟的傻瓜式操作就能很好地解決windows服務安裝和卸載的問題。
過一段時間估計還要狠狠地利用windows服務來完成一些功能,為了加深印象,又回過頭弄了一個名叫HelloWorldService的windows服務,用最簡單的demo來完成所有的操作。這個服務的功能,僅僅是在它啟動的時候創建一個HelloWorld.txt文件,里邊寫上Hello World!這幾個簡單的字母而已。
1、新建windows服務項目,我這里選擇的是Framework4.0,沒有選擇高版本是為了防止在服務在一些低版本系統上無法正常運行。

2、新建的Windows 服務項目如圖右側所示,雙擊Service1.cs,出現左側Windows 服務的 設計界面,對左側界面右擊,點擊 添加安裝程序(用於添加Windows 服務的安裝程序)。
這里貌似不需要修改Service1.cs設計界面的屬性列表中的ServiceName值(該值默認是Service1),這個值會被添加的安裝程序(ProjectInstaller.cs)中設計界面的serviceInstaller1的屬性列表中的ServiceName的值覆蓋/替代,故更改serviceInstaller1中的ServiceName值就可以了,該值就是sc delete XXX 的XXX的值。

3、添加安裝程序后項目中會生成帶有默認配置的ProjectInstaller.cs文件,如圖右側(看圖標樣子應該也是個服務文件,和Service1.cs對應),左側是該文件(服務)的設計界面

4、新建完安裝程序后,需要給ProjectInstaller.cs中默認的serviceInstaller1和serviceProcessInstaller1做一些基本的屬性設置。如下圖:
4.1、serviceInstaller1的配置:
圖1:

ServiceInstaller安裝一個類,該類擴展 ServiceBase 來實現服務。在安裝服務應用程序時由安裝實用工具調用該類。在這里主要修改其StartType屬性。此值指定了服務的啟動模式。
Automatic 指示服務在系統啟動時將由(或已由)操作系統啟動。如果某個自動啟動的服務依賴於某個手動啟動的服務,則手動啟動的服務也會在系統啟動時自動啟動。
Disabled 指示禁用該服務,以便它無法由用戶或應用程序啟動。
Manual 指示服務只由用戶(使用“服務控制管理器”)或應用程序手動啟動。
圖2:

這里作下解釋(解釋以這里的為准,圖片上的描述及名字的解釋有些不准):上圖中的Description是系統(Windows)服務中對應的服務的描述,而DisplayName是該服務的名稱,而ServiceName則是
Windows 任務管理器的服務頁中的對應項的名稱;這三個名字都可以用中文,但是ServiceName最好用英文(這個值就是 sc delete XXX的XXX對應的值)。
4.2、serviceProcessInstaller1的配置:
圖1:

ServiceProcessInstall安裝一個可執行文件,該文件包含擴展 ServiceBase 的類。該類由安裝實用工具(如 InstallUtil.exe)在安裝服務應用程序時調用。在這里主要是修改其Account屬性。
ServiceAccount指定服務的安全上下文,安全上下文定義其登錄類型。
LocalService 充當本地計算機上非特權用戶的帳戶,該帳戶將匿名憑據提供給所有遠程服務器。
LocalSystem 服務控制管理員使用的帳戶,它具有本地計算機上的許多權限並作為網絡上的計算機。
NetworkService 提供廣泛的本地特權的帳戶,該帳戶將計算機的憑據提供給所有遠程服務器。
User 由網絡上特定的用戶定義的帳戶。如果為 ServiceProcessInstaller.Account 成員指定 User,則會使系統在安裝服務時提示輸
入有效的用戶名和密碼,除非您為 ServiceProcessInstaller 實例的 Username 和 Password 這兩個屬性設置值。
圖2:

這里也作下解釋:設置Account為LocalSystem就相當於在啟動該服務時是以管理員權限來啟動的。如果上圖的Account不設置為LocalSystem而是LocalService可能啟動服務會出現以下錯誤:

想知道原因可以在系統的”事件查看器“中的”應用程序“選項中查看具體的錯誤信息,如下圖:

上圖的錯誤原因是是由於服務對文件系統的操作權限問題所引起的,將serviceProcessInstaller1中的Account由LocalService改成LocalSystem就行了。
5、以上工作完成,安裝程序配置完畢,接下來添加應用程序配置文件(如果有需要的話,很多服務項目默認有一個App.config文件的一般是不需要添加),如圖:

6、編寫windows服務主代碼:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Diagnostics; 6 using System.Linq; 7 using System.ServiceProcess; 8 using System.Text; 9 10 using System.IO; 11 12 namespace OrganizClientSocketService 13 { 14 public partial class Service1 : ServiceBase 15 { 16 private MainService _mainServ; 17 public Service1() 18 { 19 InitializeComponent(); 20 } 21 22 // 開啟服務要執行的代碼 23 protected override void OnStart(string[] args) 24 { 25 _mainServ = new MainService(); 26 _mainServ.Start(); // 開啟服務 27 } 28 29 // 停止服務要執行的代碼 30 protected override void OnStop() 31 { 32 _mainServ.Stop(); // 停止服務 33 _mainServ = null; // 釋放服務資源 34 } 35 } 36 }
7、編譯生成Windows 服務程序。
8、上面的Windows 服務項目編譯生成的都是 安裝包 最終要安裝/卸載的對象;接下來就添加一個安裝項目用來安裝上面的服務,如圖:
9、添加工程后,在默認的 視圖界面(可通過右擊安裝項目->視圖->文件系統; 打開此視圖界面) 右鍵點擊”應用程序文件夾“,選擇”添加“->”項目輸出“;(這部分也可以參照VS如何添加一個安裝項目之類的文章)

在彈出的窗口中選擇“主輸出”(記得選中項目),點擊“確定”。

注意:上面的選擇里還有個配置可選,可選項有如圖:
如果不選則默認是 (活動),它和需要打包的項目的狀態是一致的,如果待打包的項目當前是Debug的,則(活動)代表 Debug Any CPU;
如果你的待打包項目的Release和Debug是不同的,則最好手動選中Debug還是Release(比如待打包項目的Debug是測試用的窗體程序,而Release則是真正要發布的Windows服務程序,這時候最好手動選擇)

10、上面的步驟定義了最后在應用程序文件夾中包含的內容。下面來定義其他方面的內容(設置安裝程序執行的同時安裝服務到系統服務列表中,很重要)。
在項目上點右鍵,選擇 視圖->自定義操作:

出來如下的界面,然后在”自定義操作“上點右鍵,選擇”添加自定義操作“:

在彈出的窗口中雙擊”應用程序文件夾“:

然后選擇”主輸出來自HelloWorldService(活動)“(這部分要根據自己的程序進行相應的更改),點擊”確定“:

選擇之后會發現所有的操作下邊都添加了剛才選定的項,如下圖。做到這一步,就能使安裝程序卸載時不僅把程序卸載下來,也能把服務卸載下來(安裝的同時真正意義上的安裝服務)。

11、接下來在安裝項目上點右鍵,選擇”生成“,就能使安裝程序正常發布了,成功后會生成兩個文件(這里貌似只需要 .msi的文件就可以安裝了setup.exe不知道有什么用)。

// 這句話可不看:安裝成功后根據你的Windows 服務項目中服務安裝程序的配置決定是否需要手動啟動服務。
重要提示:如果想要windows服務安裝后立刻主動啟動可以在Windows Service的ProjectInstaller.cs(添加安裝程序)中增加下面的代碼:
///// <summary> ///// 修改Visual Studio 中 Windows Service的ProjectInstaller.cs中的代碼 ///// 重寫安裝完成后函數(只功能都已經安裝完成,而不是安裝窗體已經關閉) ///// 實現安裝完成后自動啟動已安裝的程序或啟動服務(可能需要管理員權限才有用),看下怎樣才能讓安裝程序必須有管理員權限。(或許可以通過C#本身的代碼實現開啟服務,而不一定要管理員權限) ///// </summary> //protected override void OnAfterInstall(IDictionary savedState) //{ // base.OnAfterInstall(savedState); // MessageBox.Show("是安裝完成后才出現的嗎?"); // 這個可以執行一個 .bat(net start XXX)來開啟Windows服務,不過需要管理員權限; //}
