最近在作一個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是作調試日誌,每一個步驟寫日誌的方式來檢測服務是否正常啓動等(我一直沒用過,暫無介紹)不過我的認爲這種方式也會有缺點.沒有斷點調試那樣直觀
不過有機會能夠試試這種方式
多說都是淚,方法和思路都是本身試出來的,有什麼代碼或思路錯誤請朋友們提出,對的點個贊,謝謝~
感謝區:
因爲不知道怎麼把評論人的名字搞到這裏來,因此只能這樣感謝大家提出的意見了,謝謝~.~