Windows服务作为本地系统帐户停留在“启动”状态

时间:2015-07-06 14:56:14

标签: c# windows-services

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

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

  

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

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

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

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

  1. 如何使用本地系统帐户正常启动服务?
  2. 如果我决定使用网络服务帐户,我应该关注什么来保证我的服务能够正常用作服务器?

6 个答案:

答案 0 :(得分:19)

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

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

答案 1 :(得分:3)

如果您的服务无法响应或在您无法停止的Windows服务中显示待处理,请使用以下说明强制服务停止。

var arrOutput = Array.from(new Set([1,2,3,4,5,5,6,7,8,9,6,7]));
alert(arrOutput);

答案 2 :(得分:0)

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

答案 3 :(得分:0)

您可以尝试使用注册表中的密钥来增加Windows服务超时

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
  

" ServicesPipeTimeout" = dword:300000(30秒)

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

答案 4 :(得分:0)

对我来说,这是一个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 :(得分:0)

查找服务的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 (0x000x000) SERVICE_EXIT_CODE : Fx0700000000000000000000000 /p>

现在终止服务:

<块引用>

taskkill /f /pid 3976

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