web-dev-qa-db-fra.com

Le service Windows est bloqué sur le statut de "démarrage" en tant que compte système local

J'ai développé un serveur http via une application console en C # et décidé de le transformer en un service Windows pour pouvoir l'initialiser sans qu'il soit nécessaire de se connecter à la machine.

J'ai suivi toutes les étapes de Comment créer un service Windows et ai choisi le compte comme étant "Système local", mais lorsque je l'installe sur mon ordinateur serveur et que j'appuie sur le bouton Démarrer, cela prend un certain temps et donne l'erreur suivante:

Erro 1053: Le service n'a pas répondu à la demande de démarrage ou de contrôle dans les délais.

Après cela, l'état du service reste bloqué au "démarrage" et l'application ne fonctionne pas et je ne peux même plus arrêter le service.

En essayant de contourner ce problème, je l'ai changé en "Service réseau", donc il a démarré normalement, mais l'application n'écoutait pas le port que j'ai défini lorsque j'ai vérifié l'invite avec la commande "netstat -an". Mais l'application écoute normalement si je l'exécute en tant qu'application console.

Je cherche donc une réponse à l'une de ces deux questions:

  1. Que dois-je faire pour que le service démarre correctement avec un compte Système local?
  2. Si je décide d'utiliser un compte de service réseau, de quoi dois-je m'occuper pour garantir le bon fonctionnement de mon service en tant que serveur?
14
joaocarlospf

Lorsque j'ai converti mon application console en service Windows, j'ai simplement placé mon code directement dans la méthode OnStart. Cependant, j’ai réalisé que la méthode OnStart devait démarrer le service, mais que le démarrage du service devait prendre un peu de temps. J'ai donc créé un thread qui exécute mon service et laissé la méthode OnStart se terminer. J'ai testé et le service a bien fonctionné. Voici comment c'était le code:

protected override void OnStart(string[] args)
{
    Listener(); // this method never returns
}

Voici comment cela a fonctionné:

protected override void OnStart(string[] args)
{
    Thread t = new Thread(new ThreadStart(Listener));
    t.Start();
}

Mais je ne comprends toujours pas pourquoi le service a fonctionné (passé le statut de "démarrage", mais ne fonctionnait pas) quand j'ai utilisé le compte de service réseau. Si quelqu'un le sait, je serai heureux de connaître la raison.

19
joaocarlospf

Si un service qui ne répond pas ou ne s'affiche pas en attente dans les services Windows et que vous ne pouvez pas arrêter, suivez les instructions ci-dessous pour forcer le service à s'arrêter.

Click the Start menu
Click Run or in the search bar type services.msc
Press Enter
Look for the service and check the Properties and identify its service name
Once found, open a command Prompt. Type sc queryex [servicename].
Press Enter
Identify the PID
In the same command Prompt type taskkill /pid [pid number] /f
Press Enter
2
Salman Lone

Pour moi, c'était une boucle while qui regardait une file d'attente externe. La boucle while a continué à fonctionner jusqu'à ce que la file d'attente soit vide. Résolu en appelant un événement timer directement uniquement lorsque Environment.UserInteractive. Par conséquent, le service pourrait être facilement mis au point, mais lorsqu’il serait exécuté en tant que service, il attendrait l’événement timers ElapsedEventHandler.

Un service:

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);
        }
    }
}

Processeur:

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;
    }
}
0
Ogglas

Vérifiez le journal des événements de l'application Windows, il pourrait contenir certaines entrées de la source d'événements générée automatiquement de votre service (qui devrait porter le même nom du service).

0
mainvoid

Vous pouvez essayer d'augmenter le délai d'expiration du service Windows avec une clé dans la base de registre.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control

"ServicesPipeTimeout" = dword: 300000 (30 secondes)

S'il n'existe pas, il doit être créé.

0
Marisco