只有累積,沒有奇蹟

2019年4月29日 星期一

[.NETCore] Windows Service - 服務並未以適時的方式回應啟動或控制請求。

前言
在上一篇有提到如何使用指令 註冊 Window Service 服務,提到了如何用指令操作 Windows Service 看啟用的狀態,但有時在啟動時會發生錯誤造成啟動失敗的狀況發生,舉例來說在啟動服務時跳出  'Windows 無法啟動,本機電腦的 TestService 服務,錯誤 1503 : 服務並未已適時的方式回應啟動獲控制請求。 這篇要說明的是在註冊服務當下發生異常的處理方式若有問題歡迎提出一起討論或是給予指導。

解決方案
首先第一步要知道啟動失敗的原因,當 Windows Service 在啟動服務失敗時,會透過 GetLastError函數回傳錯誤訊息,並將其錯誤原因與錯誤代碼做 mapping,因此在錯誤訊息中可以看到錯誤代碼 1053,每個錯誤代碼背後都代表特定錯誤原因,可以透過清單查詢代碼對應的錯誤原因 傳送門
在 1053 對應的錯誤訊息為 : The service did not respond to the start or control request in a timely fashion.,疑似執行的程式內容並未執行正確,錯誤訊息內容太籠統無法得到處理方向,因此進行下一步處理。

事件檢視器
事件檢視器 Event Viewer 是提供使用者查看電腦中發生大大小小事情的工具,Server 的啟動關閉紀錄、IIS 站台的狀況、或是當應用程式忽然異常時都會將其 Log 資訊寫到事件檢視器中,因此當 Windows Service 啟動失敗時,也可以使用事件檢視器來查看可能異常的原因,開啟方式為在左下角開始,輸入 Event 並按下 Enter
可以透過時間搜尋發生問題的當下系統中的 log 資訊,可以發現啟動時 Windows Service 紀錄的錯誤為 服務並未以適當的方式回應啟動或控制請求,根本原因是等候 TestService 服務連線時發生逾時 (30000 毫秒) 造成
回到代碼發現舊有的代碼 Console 應用程式在啟動時並未加上 Log 紀錄,因此在 Console 進入點 main 方法加上 StreamWriter 加入 log 尋找可能錯誤原因,另外在與同事討論後提到 Serilog 在作為 Windows Service 時要特別注意 Log 路徑問題,建議在使用 Serilog 在啟動時加上指定路徑,因此在 Initial Log 時加入下列代碼
private static void InitialLogging()
{
    var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
    var pathToContentRoot = Path.GetDirectoryName(pathToExe);
    Directory.SetCurrentDirectory(pathToContentRoot);

    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Debug()
        .WriteTo.Console()
        .WriteTo.File("logs/App_.txt", rollingInterval: RollingInterval.Day)
        .CreateLogger();
}
接著在開啟 cmd 輸入指令重新啟動 Windows Service,指令為  start ServiceName  要啟動時狀態為 START_PENDING (2)
D:\>sc start testservice

SERVICE_NAME: testservice
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 2  START_PENDING
                                (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x7d0
        PID                : 26300
        FLAGS              : 
當啟動完畢之後,狀態就會更新為 RUN (4) 
SERVICE_NAME: testservice
        TYPE               : 10  WIN32_OWN_PROCESS
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)
        SERVICE_EXIT_CODE  : 0  (0x0)
        CHECKPOINT         : 0x0
        WAIT_HINT          : 0x0
服務啟動正常除蟲完畢,打完收工 !!

參考
powershell create windows service

0 意見:

張貼留言

Copyright © m@rcus 學習筆記 | Powered by Blogger

Design by Anders Noren | Blogger Theme by NewBloggerThemes.com