C# 開發windows服務的一些心得

最近在作一個windows服務的項目,發現並解決了一些問題,拿出來和你們分享一下,如下windows服務簡稱「服務」windows

文章會在適合時間更新,由於朋友們在不斷提出新的意見或思路,感謝~。~ide

1.服務如何在某種狀況下彈出一個窗體?工具

第一種解決辦法,用安裝程序的代碼修改註冊表來完成:this

1.右擊服務的視圖設計界面的空白處,添加安裝程序spa

2.右擊默認的serviceProcessInstaller1-->屬性-->Account屬性設置爲LocalSystem.net

3.右擊安裝程序空白處-->查看代碼,添加如下代碼設計

public override void Install(IDictionary stateServer)
        {
            Microsoft.Win32.RegistryKey system, currentControlSet,services,    service, config;

            try
            {
            
                base.Install(stateServer);
                //打開註冊表值
                system = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("System");
                currentControlSet = system.OpenSubKey("CurrentControlSet");
                services = currentControlSet.OpenSubKey("Services");
                service = services.OpenSubKey(this.serviceInstaller1.ServiceName, true);
                //設置服務的描述
                service.SetValue("Description", "這是一個服務");
                //容許服務與桌面交互
                int value = (int)service.GetValue("Type");
                service.SetValue("Type", value | 256);
                config = service.CreateSubKey("Parameters");
            }
            catch (Exception e)
            {
                Console.WriteLine("An exception was thrown during service installation:/n" + e.ToString());
            }
        }

        public override void Uninstall(IDictionary stateServer)
        {
            Microsoft.Win32.RegistryKey system,
             currentControlSet,
             services,
             service;

            try
            {
                //Drill down to the service key and open it with write permission
                system = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("System");
                currentControlSet = system.OpenSubKey("CurrentControlSet");
                services = currentControlSet.OpenSubKey("Services");
                service = services.OpenSubKey(this.serviceInstaller1.ServiceName, true);
                //Delete any keys you created during installation (or that your service created)
                service.DeleteSubKeyTree("Parameters");
                //...
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception encountered while uninstalling service:/n" + e.ToString());
            }
            finally
            {
                //Let the project installer do its job
                base.Uninstall(stateServer);
            }
        }

 這個方法不少,也能夠在網上搜到調試

第二種解決辦法,用bat批處理文件修改註冊表完成(若是已經運行的服務不是LocalSystem帳戶,是不容許與桌面交互的)日誌

建立一個bat文件,寫入如下代碼,保存並雙擊運行,點擊 y 回車更改服務帳戶code

reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\本身服務的名稱/v ObjectName /t REG_SZ /d LocalSystem

若是想直接修改註冊表,在以上代碼前加"echo y|"   (沒有雙引號) 這樣雙擊運行的時候就能夠直接修改了

 

第三種解決辦法也是最簡單的辦法,經過手動修改

打開服務控制器,右擊要修改帳戶的服務屬性,登陸選項卡,修改成本地系統帳戶,並容許與桌面交互

 


2.服務如何獲取程序當前的路徑?

服務中使用Environment.CurrentDirectory獲取的是system32的路徑

解決辦法:添加引用:window.form

使用Application.StartupPath(獲取到程序生成的文件夾)

(其它方法暫時尚未嘗試,因此先不寫了)


3.如何使用Timer?

和form不一樣,服務有專門的Timer

右擊工具箱"選擇項",.netFrameWork組件:找到Timer

別搞成Form裏的Timer


 4服務的更新

服務有時候出了問題也會用到更新,安裝服務機子少時候能夠本身手動更新,多的話,像上百臺或更多,在作需求的時候就要想到更新程序是如此的重要

我就是在這方面吃了大虧,請朋友們引覺得戒

如兩個服務A和B,B是某某服務,A是B的更新服務,想要實現的功能:系統啓動時自動啓動A服務來檢測B服務是否有更新文件,有則下載更新,啓動B服務,無則直接啓動B服務

1.兩個服務必定要分開兩個項目來寫,若是在一個項目裏寫兩個服務,在更新的時候就會提示程序正在訪問沒法運行而更新失敗

2.B服務要設置爲手動啓動,若是早與A服務自動啓動。而且A服務檢測到有更新文件,將沒法完成B服務的更新

3.B服務設置爲手動啓動,並非讓你手動去啓動B服務。是經過A來啓動B。

啓動方式以下:

條件:B服務爲LocalSystem,而且B服務已經安裝完成

利用進程啓動B服務

public void RunService()
        {
            Process PortProcess = new Process();
            PortProcess.StartInfo.FileName = "cmd.exe";
            PortProcess.StartInfo.UseShellExecute = false;
            PortProcess.StartInfo.RedirectStandardInput = true;
            PortProcess.StartInfo.RedirectStandardOutput = true;
            PortProcess.StartInfo.RedirectStandardError = true;
            PortProcess.StartInfo.CreateNoWindow = true;
            try
            {
                PortProcess.Start();
                PortProcess.StandardInput.WriteLine("net start 服務的名稱");
                PortProcess.StandardInput.WriteLine("exit");
                PortProcess.Close();
            }
            catch (Exception)
            {
            }
        }

其它方式有待改進,暫不貼出


5服務的調試

我的知道的有兩種服務調試的方式

1是用VS,附加到進程來作調試,步驟比較簡單但也有缺點

(1)安裝和啓動一個服務之後,點擊VS中的調試-->附加到進程(注意選擇"附加到"這個選項,必定要是本身程序的代碼,我用的.net4.0,因此我選擇的是"託管4.0版代碼")

(2)找到本身的程序進程,附加便可

這種方式的缺點:由於是在啓動之後才能夠附加到進程.服務的OnStart方法沒法調試。因此我通常都會把代碼放到OnStop方法裏調試

2是作調試日誌,每一個步驟寫日誌的方式來檢測服務是否正常啓動等(我一直沒用過,暫無介紹)不過我的認爲這種方式也會有缺點.沒有斷點調試那樣直觀

不過有機會能夠試試這種方式


多說都是淚,方法和思路都是本身試出來的,有什麼代碼或思路錯誤請朋友們提出,對的點個贊,謝謝~

 

感謝區:

因爲不知道怎麼把評論人的名字搞到這裏來,因此只能這樣感謝大家提出的意見了,謝謝~.~

相關文章
相關標籤/搜索