.net Windows服務程序和安裝程序制作
最近項目中用到window服務程序,以前沒接觸過,比較陌生,花了兩天的時間學習了下,寫了個簡單的服務,但在制作安裝程序的時候,參照網上很多資料,卻都制作不成功,可能是開發環境或項目配置的不同,這里把自己成功制作的方式貼出來,一方面留給自己,一方面也希望能給遇到同樣問題絕望中不能自拔、以致失去靈魂的路人甲,路人乙一還魂丹 . . .
IDE :WIN2003 VS2008 SQL2005
一、創建window服務項目
首先我們建一個window服務項目 :解決方案(右擊)——> 增加 ——> 新建項目——>項目類型選擇Windows——>模板選擇Windows服務 ,如圖:

二、編寫Window服務程序
向導向工程文件中增加Service1.cs類:
其中各屬性的含意是:
Autolog 是否自動寫入系統的日志文件
CanHandlePowerEvent 服務時候接受電源事件
CanPauseAndContinue 服務是否接受暫停或繼續運行的請求
CanShutdown 服務是否在運行它的計算機關閉時收到通知,以便能夠調用 OnShutDown 過程 CanStop 服務是否接受停止運行的請求
ServiceName 服務名
創建后會生成兩個文件 Program.cs 和 Service1.cs ,其中 program.cs 這個文件不用動,里面已自動生成好了。我們在Service1.cs里增加所要的操作,里面有兩個重寫方法 OnStart 和 OnStop ,OnStart 方法表示服務啟動的操作,OnStop 表示服務停止的操作,下面寫了一個簡單示例 :當服務啟動后,調用遠程一個WebService的Hello函數,並把返回的值寫入到一個文件中。code如下:

/// <summary> /// 服務啟動的操作 /// </summary> /// <param name="args"></param> protected override void OnStart(string[] args) { StartHello(); } /// <summary> /// 服務停止的操作 /// </summary> protected override void OnStop() { try { ThreadHello.Abort(); Flag = false; System.Diagnostics.Trace.Write("線程停止"); } catch (Exception ex) { System.Diagnostics.Trace.Write(ex.Message); } } private Thread ThreadHello; private void StartHello() { try { // 標准形式 //ThreadStart NewThreadStart = new ThreadStart(VoidName); //Thread NewThead = new Thread(NewThreadStart); //NewThead.Start(); ThreadHello = new Thread(new ThreadStart(Hello)); ThreadHello.Start(); System.Diagnostics.Trace.Write("線程任務開始"); } catch (Exception ex) { System.Diagnostics.Trace.Write(ex.Message); throw ex; } } private void Hello() { while (Flag) { localhost.AdvService la = new WindowsService1.localhost.AdvService(); try { string helloname = la.Hello("Andy"); // 調用遠程WebService中的方法 writeInLog(helloname, false); // 把調用返回的數據寫入到文件中 } catch (Exception ex) { System.Diagnostics.Trace.Write(ex.Message); throw ex; } Thread.Sleep(5000); } } /// <summary> /// 寫入文件操作 /// </summary> /// <param name="msg">寫入內容</param> /// <param name="IsAutoDelete">是否刪除</param> private void writeInLog(string msg, bool IsAutoDelete) { try { string logFileName = @"E:\Sample\PG_Sample\log.txt"; // 文件路徑 FileInfo fileinfo = new FileInfo(logFileName); if (IsAutoDelete) { if (fileinfo.Exists && fileinfo.Length >= 1024) { fileinfo.Delete(); } } using (FileStream fs = fileinfo.OpenWrite()) { StreamWriter sw = new StreamWriter(fs); sw.BaseStream.Seek(0, SeekOrigin.End); sw.WriteLine("====================================="); sw.Write("添加日期為:" + DateTime.Now.ToString() + "\r\n"); sw.Write("日志內容為:" + msg + "\r\n"); sw.WriteLine("====================================="); sw.Flush(); sw.Close(); } } catch (Exception ex) { ex.ToString(); } }
例子很簡單,方便理解,上面通過線程,每5秒執行一次操作,到這里,我們的服務以及服務實現的功能就已經寫好了,下面怎么讓客戶端安裝我們的服務呢?這里才是我寫這篇文章的目的!先要增加一個安裝程序類,切換到視圖窗口,右擊——>增加安裝程序,便會增加一個程序安裝類文件 ProjectInstaller.cs,如圖:
這里serviceProcessInstaller1 和 serviceInstaller1 有幾個重要屬性要設置,serviceInstaller1 中的StartType要設置成Automatic,表示隨機啟動,ServiceName表示服務名稱,Description 表示服務的描述, DisplayName 表示顯示名稱。serviceProcessInstaller1 中的Account要設置成LocalSystem,表示本地系統帳號

C# 安裝布署 及Windows服務自動啟動
設置serviceInstaller1控件的StartType屬性為"Automatic"
在服務器上添加安裝程序,在 private void ProjectInstaller_AfterInstall(object sender, InstallEventArgs e) 事件中,添加以下代碼:
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
string Cmdstring = "sc start myservice"; //CMD命令 myservice服務名稱
p.StandardInput.WriteLine(Cmdstring);
p.StandardInput.WriteLine("exit");
即可在安裝服務后立刻啟動windows服務
Window服務的安裝有兩個方式:
一、命令安裝



由於我們是安裝服務,就不需要用戶桌面和程序菜單了,直接應用程序文件夾(右擊)——> 增加 ——> 項目輸出 入圖 :
上面有兩點需要注意 ,一 項目選擇中選擇要安裝的服務, 二 項目選擇下面要選擇主輸出,選擇好后確定,這一步增加了安裝程序的文件夾,下一步就是給這個安裝程序增加操作,這里我們增加兩個基本操作,一個是安裝,一個是卸載。安裝項目(右擊) ——> 視圖 ——> 自定義操作 如圖
上面可以看到有安裝,提交,回滾,卸載等操作,我們先增加安裝操作,安裝(右擊)——> 增加自定義操作,會彈出一個對話 如圖:
選擇應用程序文件夾,並選中之前增加的主輸出項,確定,這樣這個安裝程序就增加了安裝的操作,同樣按照這樣的方式增加卸載操作,卸載與安裝唯一不同的是需要設置一個命令參數,不可少,如圖:
這里 Arguments 里輸入 /u 表示卸載命令相當於 InstallUtil.exe /u 服務路徑 , 到這里 ,我們的安裝程序就已經制作好了,生成安裝程序項目,將會生成 setup.exe 和 setup.msi 安裝文件,拷貝到客戶端,點擊setup.exe 就像安裝QQ一樣安裝我們的服務,實際上比QQ好多了,QQ還有廣告,我們可是純綠色的!

--------------------------------------------------------------------------------------
1.創建 windows服務 項目 文件 -> 新建項目 -> 已安裝的模板 -> Visual C# -> windows ,在右側窗口選擇"windows 服務"
2.系統已經為我們建立了一個 Service1.cs 組件,測試時我們就用它了. 如果要新件的話,右鍵項目 -> 添加 -> 新建項 -> windows 服務。
3.在 Service1.cs 上 ,按 F7 (右鍵查看代碼),打開代碼頁。加入我們測試用的代碼。 注意:下面的幾個方法中的 str 變量,為了我們一會兒調試時設置斷點用的!

using System; using System.Diagnostics; using System.ServiceProcess; namespace WindowsService1 { public partial class Service1 : ServiceBase { public Service1() { InitializeComponent(); InitService(); } /// <summary> /// 初始化服務參數 /// </summary> private void InitService() { base.AutoLog = false; base.CanShutdown = true; base.CanStop = true; base.CanPauseAndContinue = true; base.ServiceName = "Service1"; //這個名字很重要,設置不一致會產生 1083 錯誤哦! } protected override void OnStart(string[] args) { string str ="服務開啟"; } protected override void OnStop() { string str ="服務停止"; } protected override void OnContinue() { string str ="服務繼續運行"; base.OnContinue(); } protected override void OnPause() { string str ="服務暫停"; base.OnPause(); } } }
4.建立服務的“安裝程序” 4.1 雙擊”Service1.cs“,打開 Service1.cs 的視圖設計器 4.2 在視圖設計器中任意位置右鍵,選擇”添加安裝程序“ 4.3 這時項目跟目下將出現一個 ProjectInstaller.cs 的組件 (如果是第一次添加”安裝程序“的話) 4.4 雙擊 ProjectInstaller.cs 打開 ProjectInstaller 的視圖設計器 4.5 找到 serviceInstaller1 組件,選中后按 F4 鍵,設置組件屬性。 Description=“測試服務1”; DisplayName=“Service1”; ServiceName=“Service1”;//這個值必須和 WindowsService1.InitService() 方法下設置的 base.ServiceName 屬性一至。 StartType 為服務運行類型,根據你的需要設置即可。(Manual:手動啟動,AutoMatic 為自動啟動) 4.6 找到 serviceProcessInstaller1 組件,選中后按 F4 鍵,設置組件屬性。 Account=“LocalSystem”; //設置為其他的屬性在開啟服務時,會提示輸入用戶名和密碼 4.7 這樣就完成了一個服務的所有准備,下面就是安裝和測試工作。
5.生成組件 右鍵項目,選擇“生成”。
6.安裝組件 6.1 使用 InstallUtil.exe 工具注冊組件服務,文件位置在不同版本的 framework 中。我用的是 4.0 所以在一下位置 C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe 6.2 打開生成目錄,如果生成成功會有一個 WindowsService1.exe 文件 6.3 在生成目錄根目錄下新加兩個 bat(批處理文件),用於安裝和卸載服務 新建一個文本文件,打開文件加入以下兩行命令 C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe WindowsService1.exe pause 保存后關閉文本文件,之后將其重命名為“安裝服務.bat”文件,注意要修改后綴名為 .bat!
再新建一個文本文件,打開文件加入以下兩行命令 C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe /u WindowsService1.exe pause 保存后關閉文本文件,之后將其重命名為“卸載服務.bat”文件,注意要修改后綴名為 .bat! 6.4 “安裝服務.bat”文件,安裝windows 服務
7.安裝成功后需要手動開啟服務,因為我們剛設置 serviceInstaller1.StartType 為 Manual 打開windows 服務管理器,找到名為 Service1 的服務,右鍵屬性。點擊【啟動】按鈕
8.windows 調試 8.1 回到開發環境,選擇調試->附加到進程,勾選”顯示所有用戶進程“ 8.2 找到 WindowsService1.exe 進程(如果沒有點擊下刷新按鈕),選中后點擊“附加到進程”按鈕。 8.3 選中 Service1.cs 文件,后按 F7 打開代碼視圖 8.4 在所有 str 變量上添加調試斷點 8.5 回到windows服務管理器,找 Service1 服務並選中它,在左側有一個“暫停”按鈕。點擊一下 這時,OnPause 方法下的斷點命中!OK 達到了調試的目的了
9.如果想一次安裝多個服務,需要按照 2~5 的步驟多添加幾個服務就好了! -------------------------------------------------------------------------------------- 問題及解決方案 注冊成功后,啟動 Windows服務 時遇到錯誤:1083 的解決辦法 1.查看 Main() 方法中是否啟動了指定的服務 ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new Service1(), new Service2() //如果建立多個服務需要添加這段代碼 }; ServiceBase.Run(ServicesToRun);
2.確保 ProjectInstaller.cs 視圖設計器中的 serviceInstaller1 組件的 ServiceName 屬性 與 Service1.cs 組件的 ServiceName 屬性一致