Windows 服务卡在 "starting" 本地系统帐户状态
Windows Service stuck on "starting" status as local system account
我在 C# 中通过控制台应用程序开发了一个 http 服务器,并决定将它变成一个 Windows 服务,以便能够在不需要登录机器的情况下初始化它。
我遵循了 How to create Windows Service 中的所有步骤并选择了 "Local System" 帐户,但是当我在我的服务器机器上安装并按下开始按钮时,它需要一段时间并出现以下错误:
Erro 1053: The service did not respond to the start or control request in timely fashion.
之后,服务状态一直停留在"starting",应用程序无法运行,我什至无法停止服务。
为了解决这个问题,我将其更改为 "Network Service",因此它可以正常启动,但是当我使用命令 [=33] 在提示符中检查时,应用程序并未监听我设置的端口=].但是,如果我 运行 作为控制台应用程序,应用程序会正常侦听。
所以我正在寻找以下两个问题之一的答案:
- 我应该怎么做才能使用本地系统帐户正确启动服务?
- 如果我决定使用网络服务帐户,我应该注意什么来保证我的服务作为服务器正常工作?
检查 Windows 应用程序事件日志,它可能包含来自您的服务自动生成的事件源(应与服务同名)的一些条目。
当我将控制台应用程序转换为 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();
}
但是我还是不明白为什么我使用网络服务账号时服务运行(通过了"starting"状态,但是没有工作)。如果有人知道,我会很高兴知道原因。
您可以尝试使用注册表中的键来增加windows服务超时
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
"ServicesPipeTimeout"=dword:300000 (300 seconds or 5 minutes)
如果不存在,则必须创建它。
如果您有无法停止的 Windows 服务未响应或显示待处理的服务,请按照以下说明强制停止该服务。
Start
-> Run
或 Start
-> 输入 services.msc
并按 Enter
- 查找服务并检查属性并确定其服务名称
- 找到后,打开命令提示符。输入
sc queryex [servicename]
- 识别PID(进程ID)
- 在同一命令提示符下键入
taskkill /pid [pid number] /f
对我来说,这是一个查看外部队列的 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 类型:10 WIN32_OWN_PROCESS 状态:2 0 START_PENDING (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN) WIN32_EXIT_CODE : 0 (0x0) SERVICE_EXIT_CODE : 0 (0x0) 检查点 : 0x0 WAIT_HINT : 0x0 PID : 3976 FLAGS :
现在终止服务:
taskkill /f /pid 3976
成功:PID 为 3976 的进程已终止。
我在 C# 中通过控制台应用程序开发了一个 http 服务器,并决定将它变成一个 Windows 服务,以便能够在不需要登录机器的情况下初始化它。
我遵循了 How to create Windows Service 中的所有步骤并选择了 "Local System" 帐户,但是当我在我的服务器机器上安装并按下开始按钮时,它需要一段时间并出现以下错误:
Erro 1053: The service did not respond to the start or control request in timely fashion.
之后,服务状态一直停留在"starting",应用程序无法运行,我什至无法停止服务。
为了解决这个问题,我将其更改为 "Network Service",因此它可以正常启动,但是当我使用命令 [=33] 在提示符中检查时,应用程序并未监听我设置的端口=].但是,如果我 运行 作为控制台应用程序,应用程序会正常侦听。
所以我正在寻找以下两个问题之一的答案:
- 我应该怎么做才能使用本地系统帐户正确启动服务?
- 如果我决定使用网络服务帐户,我应该注意什么来保证我的服务作为服务器正常工作?
检查 Windows 应用程序事件日志,它可能包含来自您的服务自动生成的事件源(应与服务同名)的一些条目。
当我将控制台应用程序转换为 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();
}
但是我还是不明白为什么我使用网络服务账号时服务运行(通过了"starting"状态,但是没有工作)。如果有人知道,我会很高兴知道原因。
您可以尝试使用注册表中的键来增加windows服务超时
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
"ServicesPipeTimeout"=dword:300000 (300 seconds or 5 minutes)
如果不存在,则必须创建它。
如果您有无法停止的 Windows 服务未响应或显示待处理的服务,请按照以下说明强制停止该服务。
Start
->Run
或Start
-> 输入services.msc
并按 Enter- 查找服务并检查属性并确定其服务名称
- 找到后,打开命令提示符。输入
sc queryex [servicename]
- 识别PID(进程ID)
- 在同一命令提示符下键入
taskkill /pid [pid number] /f
对我来说,这是一个查看外部队列的 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 类型:10 WIN32_OWN_PROCESS 状态:2 0 START_PENDING (NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN) WIN32_EXIT_CODE : 0 (0x0) SERVICE_EXIT_CODE : 0 (0x0) 检查点 : 0x0 WAIT_HINT : 0x0 PID : 3976 FLAGS :
现在终止服务:
taskkill /f /pid 3976
成功:PID 为 3976 的进程已终止。