原文:Creating Windows Services In .NET Core – Part 1 – The “Microsoft” Way
          作者:Dotnet Core Tutorials
          譯者:Lamond Lu
          譯文:使用.NET Core創(chuàng)建Windows服務(wù)(一) - 使用官方推薦方式



          創(chuàng)建Windows服務(wù)來運(yùn)行批處理任務(wù)或者運(yùn)行后臺任務(wù),是一種非常常見的模式,但是由于云服務(wù)(Amazon Lambda, Azure
          WebJobs以及Azure Functions)的激增,你可能不會經(jīng)常使用Windows服務(wù)了。個(gè)人而言,我非常喜歡使用Azure WebJobs,
          因?yàn)槲铱梢灾苯泳帉懸粋€(gè)控制臺程序,而不需要考慮如何云中運(yùn)行它,一個(gè)批處理文件可以將其裝換成一個(gè)自動化任務(wù),并且可以保證7*24小時(shí)的運(yùn)行。

          但是也許你還沒有使用云服務(wù),或者你有一堆要作為Windows服務(wù)運(yùn)行的舊版應(yīng)用程序需要轉(zhuǎn)換為.NET Core,
          但是不能完全將他們轉(zhuǎn)換為“無服務(wù)器”(serverless)應(yīng)用。 那么這邊文章就是適合你的。

          在許多方面,.NET Core中的Windows服務(wù)和.NET
          Framework中的Windows服務(wù)完全相同。但是,在編寫服務(wù)的時(shí)候,你可能會遇到一些小問題。此外,本文中,我們僅介紹“Microsoft”方式的Windows服務(wù)創(chuàng)建,在后續(xù),我會繼續(xù)介紹如何使用第三方庫
          TopShelf來簡化這該過程。

          安裝

          由于Visual Studio沒有提供創(chuàng)建Windows服務(wù)的模板,所以我們需要通過創(chuàng)建控制臺程序的方式來創(chuàng)建一個(gè)Windows服務(wù)。

          創(chuàng)建完成之后,我們需要安裝一個(gè)Nuget程序包,這個(gè)程序包會將一些Windows特定的API添加到.NET
          Core中,這些API實(shí)際上已經(jīng)在完整框架中提供了,但是其中許多是Windows特有的,例如Windows服務(wù)。因此, 它們并沒有包含在.NET
          Core的基礎(chǔ)庫中,但是可以通過將Nuget程序包的方式引入到.NET Core中。
          下面我們就可以在Package Manager Console中輸入以下命令。
          Install-Package Microsoft.Windows.Compatibility
          代碼

          以上引入的Nuget程序包中,最讓我們感興趣的是ServiceBase
          類。這是一個(gè)用于編寫Windows服務(wù)的基類,它提供了一系列的事件鉤子,包含服務(wù)啟動、結(jié)束、暫停等。

          下面呢,我們將在代碼中創(chuàng)建一個(gè)類,這個(gè)類負(fù)責(zé)將一些簡單的日志輸出到一個(gè)臨時(shí)文件中。我們將使用這個(gè)例子來了解其中的原理。我們的代碼如下:
          class LoggingService : ServiceBase { private const string _logFileLocation =
          @"C:\temp\servicelog.txt"; private void Log(string logMessage) {
          Directory.CreateDirectory(Path.GetDirectoryName(_logFileLocation));
          File.AppendAllText(_logFileLocation, DateTime.UtcNow.ToString() + " : " +
          logMessage + Environment.NewLine); } protected override void OnStart(string[]
          args) { Log("Starting"); base.OnStart(args); } protected override void OnStop()
          { Log("Stopping"); base.OnStop(); } protected override void OnPause() {
          Log("Pausing"); base.OnPause(); } }
          所以這里你會注意到,我們的類是繼承了ServiceBase類,并且我們重寫了幾個(gè)事件方法,輸出了一些日志。在服務(wù)啟動時(shí),會觸發(fā)OnStart
          事件,在服務(wù)終止的時(shí)候,會觸發(fā)OnStop事件。這里我們不應(yīng)該將過于繁重的任務(wù)放置在OnStart事件中來處理。

          如果我們想從Main方式中啟動這個(gè)服務(wù),代碼非常的簡單。
          static void Main(string[] args) { ServiceBase.Run(new LoggingService()); }
          以上就是全部代碼。

          服務(wù)部署

          在發(fā)布服務(wù)的時(shí)候,我們不可能僅依靠Visual
          Studio來構(gòu)建我們所需要的服務(wù),我們還需要專門針對Windows運(yùn)行時(shí)進(jìn)行構(gòu)建。為此,我們需要在項(xiàng)目根目錄的命令提示符下運(yùn)行以下命令。注意,這里我們傳入了一個(gè)
          -r標(biāo)記來告訴它要構(gòu)建那個(gè)平臺。
          dotnet publish -r win-x64 -c Release
          命令運(yùn)行完畢之后,我們可以檢查以下/bin/release/netcoreappX.X/publish
          目錄,我們可以找到所有的發(fā)布代碼,但是最重要的是,這里我們可以得到一個(gè)可執(zhí)行的exe文件。如果我們不指定運(yùn)行時(shí),我們只會獲得一個(gè).NET
          Core的dll程序集,使用這個(gè)程序集,我們是沒有辦法創(chuàng)建Windows服務(wù)的。

          現(xiàn)在我們可以將這個(gè)發(fā)布目錄移動帶其他的任何地方,但是現(xiàn)在我們就暫時(shí)使用當(dāng)前的發(fā)布目錄。

          下一步,我們需要使用管理員角色打開一個(gè)命令提示符,然后輸入一下命令。
          sc create TestService
          BinPath=C:\full\path\to\publish\dir\WindowsServiceExample.exe
          SC命令是一個(gè)標(biāo)準(zhǔn)的Windows命令(與.NET Core無關(guān)),它可以用來安裝Windows服務(wù)。這里我們將我們的測試服務(wù)命名為TestService
          ,更重要的是,我們通過BinPath參數(shù)指定了可執(zhí)行exe文件。

          運(yùn)行之后,我們應(yīng)該會得到以下結(jié)果。
          [SC] CreateService SUCCESS
          然后我們要做的就是啟動服務(wù)。
          sc start TestService
          現(xiàn)在我們可以查看一下我們的日志文件,查看服務(wù)的運(yùn)行情況。

          如果想要停止并刪除服務(wù),我們可以使用一下命令。
          sc stop TestService sc delete TestService
          服務(wù)調(diào)試

          在這里,我真的認(rèn)為,使用"Microsoft"的方式注定會失敗。因?yàn)檎{(diào)試服務(wù)實(shí)在是太繁瑣了。

          首先,我們將ServiceBase
          中重寫的方法設(shè)置為受保護(hù),這意味著我們無法在類之外訪問它們,這使得調(diào)試它們變得更加困難。這里我發(fā)現(xiàn)最好的方法是為每個(gè)事件提供一個(gè)public方法,
          并在受保護(hù)方法中調(diào)用這些public方法來完成功能,這雖然有點(diǎn)混亂,
          public void OnStartPublic(string[] args) { Log("Starting"); } protected
          override void OnStart(string[] args) { OnStartPublic(args); base.OnStart(args);
          }
          但是至少我們可以做如下了事情了。
          static void Main(string[] args) { var loggingService = new LoggingService();
          if (true) //Some check to see if we are in debug mode (Either #IF Debug etc or
          an app setting) { loggingService.OnStartPublic(new string[0]); while(true) {
          //Just spin wait here. Thread.Sleep(1000); } //Call stop here etc. } else {
          ServiceBase.Run(new LoggingService()); } }
          你的另一個(gè)選擇是,在調(diào)試模式下進(jìn)行項(xiàng)目發(fā)布,安裝服務(wù),然后附加調(diào)試器。實(shí)際上,這是Microsoft建議你使用的方式,但是我認(rèn)為這簡直一團(tuán)糟。

          后續(xù)

          實(shí)際上,我們可以在這里做一些其他非常有用的事情, 比如我們可以通過創(chuàng)建一個(gè)install.bat批處理文件來為我們運(yùn)行SC
          Create命令。但我認(rèn)為,上面我們看到的調(diào)試問題,已經(jīng)讓我不再想使用這種方式了。 幸運(yùn)的是,有一個(gè)名為Topshelf
          的庫可以幫助我們減輕很多麻煩,在本系列的下一部分中,我們將研究如何它。

          友情鏈接
          ioDraw流程圖
          API參考文檔
          OK工具箱
          云服務(wù)器優(yōu)惠
          阿里云優(yōu)惠券
          騰訊云優(yōu)惠券
          京東云優(yōu)惠券
          站點(diǎn)信息
          問題反饋
          郵箱:[email protected]
          QQ群:637538335
          關(guān)注微信

                一级全黄45分钟免费看 | 国产18禁美女黄禁片免费网站 | 无遮挡羞羞视频 | 中文天堂av | www.91在线 |