1.Windows服務簡單介紹
Windows服務程式是在Windows作業系統下能完成特定功能的可執行的應用程式,主要用於長時間執行的功能或者執行定時任務。一般情況下,使用者不能通過使用者介面來安裝和啟動Windows服務程式,服務的啟動方式有自動啟動和手動啟動兩種。我們可以在執行中輸入services.msc 命令開啟服務管理介面,在這裡可以進行啟動或者停止服務:
2.C#開發windows服務
1.windows服務開發流程
1.1 windows的基本開發流程
使用.Net可以很方便地開發windows服務,下邊通過一個栗子演示下開發windows服務的簡單流程。
首先建立一個Windows服務專案,如下圖我們建立了一個叫MyService的服務專案
然後開啟自動生成的Service1.cs,該檔案預設有兩個方法: OnStart()和OnStop() ,OnStart()指定當服務啟動時要執行的操作,OnStop()指定當服務停止時要執行的操作。 我們重寫OnStart()方法,讓服務開啟的時候,每隔一秒在一個文字檔案中記錄當前時間,程式碼如下圖
然後在右鍵Service1.cs檔案,選擇檢視設計器,在介面上右鍵選擇新增安裝程式,如下圖
修改serviceInstaller和serviceProcessInstaller,如下圖所示,到這裡服務的建立工作就完成了
1.2 安裝和解除安裝Windows服務專案
我們先通過下邊命令來安裝和解除安裝服務,其中第二行命令用於安裝服務,命令的地址是我們服務專案生成的exe檔案所在路徑,第三行命令用於解除安裝服務。
cd C:\Windows\Microsoft.NET\Framework\v4.0.30319 InstallUtil C:\Users\ZDZN\source\repos\WindowsServiceDemo\WindowsServiceInstall\bin\Debug\MyService.exe ----------安裝服務
InstallUtil -u C:\Users\ZDZN\source\repos\WindowsServiceDemo\WindowsServiceInstall\bin\Debug\MyService.exe ----------解除安裝服務
執行成功後在服務管理介面可以看到我們剛才安裝的服務,這說明服務已經安裝成功了:
我們可以在命令列中通過以下命令控制服務的開啟和停止:
net start MyService //開啟服務 net stop MyService //停止服務
如果程式沒有錯誤的話,服務啟動後會在F盤中生成一個hello.txt檔案,內容如下:
2.通過Winform控制windows服務
雖然通過命令列可以實現Windows服務的安裝、解除安裝、啟動、停止等操作,但是這樣對於使用者來說還是太過麻煩。如果能通過Winform來實現這些功能,使用者使用起來就方便多了。怎麼讓Winform控制windows服務呢?
首先要知道的一些知識:使用AssemblyInstaller可以進行Windows服務的安裝和解除安裝,ServiceController可以控制windows服務的啟動,停止,暫停,繼續等,知道了這些就容易實現了。
新增一個winform應用程式,引用我們的服務專案,程式程式碼如下,這裡的命名都很明顯就不詳細說明:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } //設定服務地址和服務名 string serviceFilePath = $"{Application.StartupPath}/MyService.exe"; string serviceName = "MyService"; private void btnInstall_Click(object sender, EventArgs e) { Task.Run(() => { ShowMessage("開始安裝服務..."); if (IsServiceExisted(serviceName)) { UninstallService(serviceFilePath); } InstallService(serviceFilePath); }); } private void btnStart_Click(object sender, EventArgs e) { Task.Run(() => { ShowMessage("服務正在啟動..."); if (IsServiceExisted(serviceName)) { ServiceStart(serviceName); ShowMessage("服務已啟動"); } }); } private void btnStop_Click(object sender, EventArgs e) { Task.Run(() => { ShowMessage("服務正在停止..."); if (IsServiceExisted(serviceName)) { ServiceStop(serviceName); ShowMessage("服務已停止"); } }); } private void btnUninstall_Click(object sender, EventArgs e) { Task.Run(() => { ShowMessage("開始解除安裝服務..."); if (this.IsServiceExisted(serviceName)) { this.ServiceStop(serviceName); } this.UninstallService(serviceFilePath); }); } #region 方法封裝 private void ShowMessage(string s) { Action setState = () => { myTxtBox.AppendText(DateTime.Now.ToString("f") + ":"); myTxtBox.AppendText(Environment.NewLine); myTxtBox.AppendText(s); myTxtBox.AppendText(Environment.NewLine); }; myTxtBox.Invoke(setState); } //判斷服務是否存在 private bool IsServiceExisted(string serviceName) { try { ServiceController[] services = ServiceController.GetServices(); foreach (ServiceController sc in services) { if (sc.ServiceName.ToLower() == serviceName.ToLower()) { return true; } } return false; } catch (Exception ex) { ShowMessage(ex.Message); return false; } } //安裝服務 private void InstallService(string serviceFilePath) { try { using (AssemblyInstaller installer = new AssemblyInstaller()) { installer.UseNewContext = true; installer.Path = serviceFilePath; IDictionary savedState = new Hashtable(); installer.Install(savedState); installer.Commit(savedState); ShowMessage("服務安裝完成"); } } catch (Exception ex) { ShowMessage(ex.Message); } } //解除安裝服務 private void UninstallService(string serviceFilePath) { try { using (AssemblyInstaller installer = new AssemblyInstaller()) { installer.UseNewContext = true; installer.Path = serviceFilePath; installer.Uninstall(null); ShowMessage("服務解除安裝完成"); } } catch (Exception ex) { ShowMessage(ex.Message); } } //啟動服務 private void ServiceStart(string serviceName) { try { using (ServiceController control = new ServiceController(serviceName)) { if (control.Status == ServiceControllerStatus.Stopped) { control.Start(); } } } catch (Exception ex) { ShowMessage(ex.Message); } } //停止服務 private void ServiceStop(string serviceName) { try { using (ServiceController control = new ServiceController(serviceName)) { if (control.Status == ServiceControllerStatus.Running) { control.Stop(); } } } catch (Exception ex) { ShowMessage(ex.Message); } } #endregion #region 頁面元素 private void Form1_Load(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; timer1.Interval = 100; timer1.Enabled = true; } //btn狀態 private void ButtonState() { if (IsServiceExisted(serviceName)) { btnInstall.Enabled = false; btnUninstall.Enabled = true; using (var service = new ServiceController(serviceName)) { if (service.Status == ServiceControllerStatus.Running || service.Status == ServiceControllerStatus.StartPending) { btnUninstall.Enabled = false; btnStart.Enabled = false; btnStop.Enabled = true; } else { btnUninstall.Enabled = true; btnStart.Enabled = true; btnStop.Enabled = false; } } } else { btnInstall.Enabled = true; btnUninstall.Enabled = false; btnStart.Enabled = false; btnStop.Enabled = false; } } //底部label狀態 private void LabelState() { if (!IsServiceExisted(serviceName)) { this.labState.Text = $"【{serviceName}】服務未安裝"; return; } using (var service = new ServiceController(serviceName)) { switch (service.Status) { case ServiceControllerStatus.Running: this.labState.Text = $"【{serviceName}】服務已啟動"; break; case ServiceControllerStatus.StartPending: this.labState.Text = $"【{serviceName}】服務正在啟動..."; break; case ServiceControllerStatus.Stopped: this.labState.Text = $"【{serviceName}】服務已停止"; break; case ServiceControllerStatus.StopPending: this.labState.Text = $"【{serviceName}】服務正在停止..."; break; default: break; } } } private void timer1_Tick(object sender, EventArgs e) { ButtonState(); LabelState(); } #endregion }
完成這一步後,我們就可以通過視覺化介面對服務的安裝,解除安裝,執行,停止進行控制了。
補充:使用TopShelf也可以實現Windows服務的快速開發,參考文件 http://docs.topshelf-project.com/en/latest/index.html