.net Windows服務程序和安裝程序制作圖解 及 VS 2010創建、安裝、調試 windows服務(windows service)


.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();
            }
        }
View Code

 

      例子很簡單,方便理解,上面通過線程,每5秒執行一次操作,到這里,我們的服務以及服務實現的功能就已經寫好了,下面怎么讓客戶端安裝我們的服務呢?這里才是我寫這篇文章的目的!先要增加一個安裝程序類,切換到視圖窗口,右擊——>增加安裝程序,便會增加一個程序安裝類文件 ProjectInstaller.cs,如圖:

這里serviceProcessInstaller1 和 serviceInstaller1 有幾個重要屬性要設置,serviceInstaller1 中的StartType要設置成Automatic,表示隨機啟動,ServiceName表示服務名稱,Description 表示服務的描述, DisplayName 表示顯示名稱。serviceProcessInstaller1 中的Account要設置成LocalSystem,表示本地系統帳號

 

C# 安裝布署 及Windows服務自動啟動

 
設置serviceProcessInstaller1控件的Account屬性為“LocalSystem”
設置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服務的安裝有兩個方式:

      一、命令安裝

       通過命令窗口,執行 InstallUtil.exe 服務路徑 可安裝Window服務,你是不是覺得我在扯,這么長的命令怎么看?怎么記住?可以想想如果客戶端是一個不懂程序的人是不可能自己完成安裝的,那么能不能制作一個簡單有效,點點按鈕可以安裝的呢,答案是肯定的 ——> 安裝程序制作
       二、安裝程序
       安裝程序制作 :解決方案(右擊)——> 增加 ——> 新建項目 ——> 項目類型選擇安裝和部署 ——>  模板選擇安裝項目   如圖 :
 
     創建后,安裝項目(右擊) ——> 視圖 ——> 文件系統 如圖:
 

     由於我們是安裝服務,就不需要用戶桌面和程序菜單了,直接應用程序文件夾(右擊)——> 增加 ——> 項目輸出 入圖 :

       上面有兩點需要注意 ,一 項目選擇中選擇要安裝的服務, 二 項目選擇下面要選擇主輸出,選擇好后確定,這一步增加了安裝程序的文件夾,下一步就是給這個安裝程序增加操作,這里我們增加兩個基本操作,一個是安裝,一個是卸載。安裝項目(右擊) ——> 視圖 ——> 自定義操作 如圖

       上面可以看到有安裝,提交,回滾,卸載等操作,我們先增加安裝操作,安裝(右擊)——> 增加自定義操作,會彈出一個對話 如圖:

      選擇應用程序文件夾,並選中之前增加的主輸出項,確定,這樣這個安裝程序就增加了安裝的操作,同樣按照這樣的方式增加卸載操作,卸載與安裝唯一不同的是需要設置一個命令參數,不可少,如圖:

      這里 Arguments 里輸入 /u  表示卸載命令相當於 InstallUtil.exe /u 服務路徑  , 到這里 ,我們的安裝程序就已經制作好了,生成安裝程序項目,將會生成 setup.exe 和 setup.msi 安裝文件,拷貝到客戶端,點擊setup.exe 就像安裝QQ一樣安裝我們的服務,實際上比QQ好多了,QQ還有廣告,我們可是純綠色的!

 
在一個應用程序中創建多個 windows 服務的方法和 1083 的解決辦法 錯誤解決方案

--------------------------------------------------------------------------------------

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();
    }
   }
  }
View Code

 

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 屬性一致


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM