【问题标题】:Windows Service stuck on "starting" status as local system accountWindows 服务作为本地系统帐户停留在“启动”状态
【发布时间】:2015-09-23 18:58:41
【问题描述】:

我在 C# 中通过控制台应用程序开发了一个 http 服务器,并决定将其转换为 Windows 服务,以便能够在无需登录机器的情况下对其进行初始化。

我按照How to create Windows Service 中的所有步骤操作并选择帐户为“本地系统”,但是当我安装在我的服务器机器上并按下开始按钮时,它需要一段时间并给出以下错误:

错误 1053:服务未及时响应启动或控制请求。

之后,服务状态一直停留在“正在启动”,应用程序无法运行,我什至无法停止服务。

为了解决这个问题,我将其更改为“网络服务”,所以它可以正常启动,但是当我使用命令“netstat -an”检查提示时,应用程序没有监听我设置的端口。但是如果我将它作为控制台应用程序运行,应用程序会正常侦听。

所以我正在寻找以下两个问题之一的答案:

  1. 我应该怎么做才能使用本地系统帐户正确启动服务?
  2. 如果我决定使用网络服务帐户,我应该注意什么来保证我的服务作为服务器正常工作?

【问题讨论】:

标签: c# windows-services


【解决方案1】:

当我将控制台应用程序转换为 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();
}

但我仍然不明白为什么我使用网络服务帐户时服务运行(通过“启动”状态,但没有工作)。如果有人知道,我会很高兴知道原因。

【讨论】:

  • 最好的猜测是对 Listener() 的调用静默失败,可能是因为网络服务缺少必要的访问权限,并且错误检查不够全面。
  • 我用一个不返回的有目的的无限循环做了类似的事情。我最终以Task.Run(() => MyMethod()); 开始了它
  • 如果它是一个http服务器,它可能正在等待连接,并且永远不会返回,这就是为什么 Listener() 永远不会返回并且服务始终处于“启动”模式的原因;做线程是正确的解决方案
  • 这很奇怪!之前我在 async OnStart 方法中做所有事情时它是有效的,但现在我必须按照你的回答才能让它工作
【解决方案2】:

如果您的某个服务没有响应或在您无法停止的 Windows 服务中显示为挂起,请使用以下说明强制停止该服务。

  • Start -> RunStart -> 输入 services.msc 并按 Enter
  • 查找服务并检查属性并确定其服务名称
  • 找到后,打开命令提示符。输入sc queryex [servicename]
  • 识别 PID(进程 ID)
  • 在同一命令提示符下键入taskkill /pid [pid number] /f

【讨论】:

  • 运行sc queryex 命令后,如果不通;你应该在cmd中运行命令,或者在powershell中执行cmd命令。
【解决方案3】:

检查 Windows 应用程序事件日志,它可能包含来自服务自动生成的事件源的一些条目(应该与服务具有相同的名称)。

【讨论】:

  • 我检查了,但没有发现与我的服务相关的日志。我在我的问题中添加了更多信息:当我尝试启动服务时,我收到以下错误:错误 1053:服务没有及时响应启动或控制请求。我搜索这个错误,但它主要与 windows server 2003 中包含的错误有关。我的 windows server 是 2012,所以我认为错误修复不适用于案例。你怎么看?
【解决方案4】:

对我来说,这是一个查看外部队列的 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;
    }
}

【讨论】:

    【解决方案5】:

    您可以尝试使用注册表中的某个键来增加 Windows 服务超时时间

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
    

    "ServicesPipeTimeout"=dword:300000(300 秒或 5 分钟)

    如果它不存在,则必须创建它。

    【讨论】:

    【解决方案6】:

    查找服务的 PID

    sc queryex

    下面给出结果

    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 : 0 (0x0) CHECKPOINT : 0x0 WAIT_HINT : 0x0 /p>

    现在终止服务:

    taskkill /f /pid 3976

    成功:PID 3976 的进程已终止。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-01
      相关资源
      最近更新 更多