[英]Windows Service stuck on "starting" status as local system account
我通過 C# 中的控制台應用程序開發了一個 http 服務器,並決定將其轉換為 Windows 服務,以便無需登錄機器即可對其進行初始化。
我按照如何創建 Windows 服務中的所有步驟並選擇帳戶作為“本地系統”,但是當我在我的服務器機器上安裝並按下開始按鈕時,它需要一段時間並給出以下錯誤:
錯誤 1053:服務沒有及時響應啟動或控制請求。
之后,服務狀態停留在“正在啟動”,應用程序無法運行,我什至無法停止服務。
試圖解決此問題,我將其更改為“網絡服務”,因此它可以正常啟動,但是當我使用命令“netstat -an”檢查提示符時,應用程序沒有偵聽我設置的端口。 但是,如果我將其作為控制台應用程序運行,該應用程序會正常偵聽。
因此,我正在尋找以下兩個問題之一的答案:
當我將控制台應用程序轉換為 Windows 服務時,我只是將代碼直接放在 OnStart 方法中。 但是,我意識到 OnStart 方法應該啟動服務,但需要結束一段時間才能真正啟動服務。 所以我創建了一個線程來運行我的服務並讓 OnStart 方法完成。 我測試過,服務運行得很好。 代碼如下:
protected override void OnStart(string[] args)
{
Listener(); // this method never returns
}
這是它的工作原理:
protected override void OnStart(string[] args)
{
Thread t = new Thread(new ThreadStart(Listener));
t.Start();
}
但是我仍然不明白為什么我使用網絡服務帳戶時服務運行(通過了“啟動”狀態,但沒有工作)。 如果有人知道,我會很高興知道原因。
如果您的某個服務沒有響應或在您無法停止的 Windows 服務中顯示掛起,請使用以下說明強制停止該服務。
Start
-> Run
或Start
-> 鍵入services.msc
並按Entersc queryex [servicename]
taskkill /pid [pid number] /f
檢查 Windows 應用程序事件日志,它可能包含來自服務自動生成的事件源的一些條目(應該與服務具有相同的名稱)。
您可以嘗試使用注冊表中的一個鍵來增加 Windows 服務超時
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
"ServicesPipeTimeout"=dword:300000(300 秒或 5 分鍾)
如果它不存在,則必須創建它。
對我來說,這是一個查看外部隊列的 while 循環。 while 循環繼續運行,直到隊列為空。 僅在Environment.UserInteractive
時直接調用計時器事件解決了它。 因此,該服務可以輕松調試,但是當作為服務運行時,它將等待計時器ElapsedEventHandler
事件。
服務:
partial class IntegrationService : ServiceBase
{
private static Logger logger = LogManager.GetCurrentClassLogger();
private System.Timers.Timer timer;
public IntegrationService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
// Add code here to start your service.
logger.Info($"Starting IntegrationService");
var updateIntervalString = ConfigurationManager.AppSettings["UpdateInterval"];
var updateInterval = 60000;
Int32.TryParse(updateIntervalString, out updateInterval);
var projectHost = ConfigurationManager.AppSettings["ProjectIntegrationServiceHost"];
var projectIntegrationApiService = new ProjectIntegrationApiService(new Uri(projectHost));
var projectDbContext = new ProjectDbContext();
var projectIntegrationService = new ProjectIntegrationService(projectIntegrationApiService, projectDbContext);
timer = new System.Timers.Timer();
timer.AutoReset = true;
var integrationProcessor = new IntegrationProcessor(updateInterval, projectIntegrationService, timer);
timer.Start();
}
catch (Exception e)
{
logger.Fatal(e);
}
}
protected override void OnStop()
{
try
{
// Add code here to perform any tear-down necessary to stop your service.
timer.Enabled = false;
timer.Dispose();
timer = null;
}
catch (Exception e)
{
logger.Fatal(e);
}
}
}
處理器:
public class IntegrationProcessor
{
private static Logger _logger = LogManager.GetCurrentClassLogger();
private static volatile bool _workerIsRunning;
private int _updateInterval;
private ProjectIntegrationService _projectIntegrationService;
public IntegrationProcessor(int updateInterval, ProjectIntegrationService projectIntegrationService, Timer timer)
{
_updateInterval = updateInterval;
_projectIntegrationService = projectIntegrationService;
timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
timer.Interval = _updateInterval;
//Don't wait for first elapsed time - Should not be used when running as a service due to that Starting will hang up until the queue is empty
if (Environment.UserInteractive)
{
OnTimedEvent(null, null);
}
_workerIsRunning = false;
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
try
{
if (_workerIsRunning == false)
{
_workerIsRunning = true;
ProjectInformationToGet infoToGet = null;
_logger.Info($"Started looking for information to get");
//Run until queue is empty
while ((infoToGet = _projectIntegrationService.GetInformationToGet()) != null)
{
//Set debugger on logger below to control how many cycles the service should run while debugging.
var watch = System.Diagnostics.Stopwatch.StartNew();
_logger.Info($"Started Stopwatch");
_logger.Info($"Found new information, updating values");
_projectIntegrationService.AddOrUpdateNewInformation(infoToGet);
_logger.Info($"Completed updating values");
watch.Stop();
_logger.Info($"Stopwatch stopped. Elapsed seconds: {watch.ElapsedMilliseconds / 1000}. " +
$"Name queue items: {infoToGet.NameQueueItems.Count} " +
$"Case queue items: {infoToGet.CaseQueueItems.Count} " +
$"Fee calculation queue items: {infoToGet.FeeCalculationQueueItems.Count} " +
$"Updated foreign keys: {infoToGet.ShouldUpdateKeys}");
}
_logger.Info($"Nothing more to get from integration service right now");
_workerIsRunning = false;
}
else
{
_logger.Info($"Worker is already running! Will check back again after {_updateInterval / 1000} seconds");
}
}
catch (DbEntityValidationException exception)
{
var newException = new FormattedDbEntityValidationException(exception);
HandelException(newException);
throw newException;
}
catch (Exception exception)
{
HandelException(exception);
//If an exception occurs when running as a service, the service will restart and run again
if (Environment.UserInteractive)
{
throw;
}
}
}
private void HandelException(Exception exception)
{
_logger.Fatal(exception);
_workerIsRunning = false;
}
}
查找服務的PID
sc queryex <SERVICE_NAME>
給出結果如下
SERVICE_NAME: Foo.Services.Bar TYPE : 10 WIN32_OWN_PROCESS STATE : 2 0 START_PENDING (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN) WIN32_EXIT_CODE : 0 (0x0) SERVICE_EXIT_CODE : 0x 6 PID 0x70x00x 0x00x 0x00x 0x00x000
現在終止服務:
taskkill /f /pid 3976
成功:PID 為 3976 的進程已終止。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.