應用情境:我的WCF服務以Windows服務形式承載,如圖
(Service右鍵-》添加安裝程式)
此種方式通常進行版本升級的時候需要將舊版本手動卸載,再安裝新版本,麻煩。若直接安裝新版本,則會報類似“Windows服務已經存在”的異常,此異常是因為舊版的服務還存在。
因此,圖方便的話,還需要安裝新版服務之前卸載服務,可以在ProjectInstaller裡解決,代碼如下:
[RunInstaller(true)] public partial class ProjectInstaller : System.Configuration.Install.Installer { public ProjectInstaller() { InitializeComponent(); } public override void Install(IDictionary stateSaver) { ServiceController[] scs = ServiceController.GetServices(); if (scs.Count(it => it.ServiceName == "PhipService") > 0) { ServiceController srvControler = new ServiceController("PhipService"); if (srvControler != null) { if (srvControler.CanStop) { srvControler.Stop(); } RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SYSTEM\ControlSet001\Services\" + srvControler.ServiceName); if (key != null) { object obj = key.GetValue("ImagePath"); if (obj != null) { string path = obj.ToString(); string file = Environment.GetEnvironmentVariable("TEMP") + "intstsrv.exe"; byte[] buffer = Resource.Instsrv; FileStream FS = new FileStream(file, FileMode.Create);//建立檔案 BinaryWriter BWriter = new BinaryWriter(FS);//以二進位開啟檔案流 BWriter.Write(buffer, 0, buffer.Length);//從資源檔讀取檔案內容,寫入到一個檔案中 BWriter.Close(); FS.Close(); Process proc = Process.Start(file, string.Format("{0} REMOVE", srvControler.ServiceName)); proc.WaitForExit(); if(File.Exists(file)) { File.Delete(file); } } } } } base.Install(stateSaver); } public override void Commit(IDictionary savedState) { base.Commit(savedState); try { string dir = Path.GetDirectoryName(base.Context.Parameters["assemblypath"].ToString()); if (dir[dir.Length - 1] != '\\') { dir += "\\"; } string fileName = dir.ToString() + "Phip.SE.Server.Configurator.exe"; string configName = dir.ToString() + "Phip.SE.Server.WinService.exe.config"; if (System.IO.File.Exists(fileName)) { System.Diagnostics.Process.Start(fileName, configName.Replace(' ', '@')); } else { MessageBox.Show("檔案不存在[" + dir + "Phip.SE.Server.WinService.exe.config]"); } } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); throw ex; } } }
如果只解決卸載服務的問題,則Commit可以忽略,需要注意的是 intstsrv.exe 是放在Service項目的資源檔裡,以保證Install函數執行的時候能找到該檔案。