Je souhaite déboguer un service Windows, mais un message d'erreur s'affiche:
Impossible de démarrer le service à partir de la commande ligne ou un débogueur. Un service Windows doit être installé avec installutil.exe et ensuite démarré avec l'explorateur de serveurs, services Windows Outils d'administration ou le démarrage net commander.
Je n'ai vraiment aucune idée de cette erreur .....
Avant qu'un service Windows puisse fonctionner, il doit d'abord être "installé" à l'aide de installutil. PAR EXEMPLE:
C:\installutil -i c:\path\to\project\debug\service.exe
Ensuite, vous pouvez ouvrir la liste des services pour le démarrer. PAR EXEMPLE:
Une fois lancé, vous pouvez accéder à Visual Studio, cliquer sur «Déboguer», puis sur «Joindre au processus».
Une autre technique consiste à ajouter cette ligne à votre méthode OnStart () dans le service:
System.Diagnostics.Debugger.Launch();
Dans ce cas, vous serez invité à choisir une instance de Visual Studio pour déboguer le service.
Vous pouvez modifier le mode de démarrage de l'assembly en fonction du mode de débogage (généralement dans Visual Studio mais pas nécessairement) ou en mode RELEASE (lorsqu'il est exécuté en tant que service en production):
Change ça:
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService()
};
ServiceBase.Run(ServicesToRun);
}
}
pour que:
static class Program
{
static void Main()
{
#if(!DEBUG)
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService()
};
ServiceBase.Run(ServicesToRun);
#else
MyService myServ = new MyService();
myServ.Process();
// here Process is my Service function
// that will run when my service onstart is call
// you need to call your own method or function name here instead of Process();
#endif
}
}
La technique est tirée de cet article et le mérite revient à l'auteur de l'article, Tejas Vaishnav. J'ai copié les fragments de code ici parce que SO préfère les réponses complètes aux liens qui pourraient disparaître un jour.
Pour éviter cette erreur et permettre au service de s'exécuter en dehors du contrôleur de service habituel, vous pouvez vérifier l'indicateur Environment.UserInteractive
. Si cette option est définie, vous pouvez exécuter le service avec une sortie sur la console au lieu de le laisser s'exécuter sur le code ServiceBase qui renvoie cette erreur.
Ajoutez ceci au début de Program.Main (), avant le code qui utilise ServiceBase pour exécuter le service:
if (Environment.UserInteractive)
{
var service = new WindowsService();
service.TestInConsole(args);
return;
}
Comme les méthodes OnStart et OnStop sont protected
dans votre service, vous devez ajouter une autre méthode à cette classe que vous pouvez exécuter à partir de Main () et appeler ces méthodes pour vous, telles que:
public void TestInConsole(string[] args)
{
Console.WriteLine($"Service starting...");
this.OnStart(args);
Console.WriteLine($"Service started. Press any key to stop.");
Console.ReadKey();
Console.WriteLine($"Service stopping...");
this.OnStop();
Console.WriteLine($"Service stopped. Closing in 5 seconds.");
System.Threading.Thread.Sleep(5000);
}
Enfin, assurez-vous que la sortie est une application console dans les propriétés du projet.
Vous pouvez maintenant exécuter le service exécutable comme un autre et il démarrera en tant que console. Si vous le démarrez à partir de Visual Studio, le débogueur se joindra automatiquement. Si vous l'enregistrez et le démarrez en tant que service, il fonctionnera correctement en tant que service sans aucune modification.
La seule différence que j'ai constatée est que, lorsqu'il est exécuté en tant qu'application console, le code n'écrit pas dans le journal des événements. Vous pouvez également générer tout ce que vous y connecteriez normalement à la console.
Cette technique de débogage de service est l’une de celles expliquées dans docs.Microsoft.com
Veuillez vérifier si vous êtes en mode "DEBUG" ou "RELEASE". J'ai eu cette erreur lorsque j'essayais de déboguer le service en mode "RELEASE". Quand j'ai changé cela en "DEBUG", tout a bien fonctionné.
Ceci est après que vous ayez correctement installé le service comme suggéré par les autres personnes ci-dessus.
Un paquet de nuget a été créé pour résoudre ce problème: install-package WindowsService.Gui
Que fait le paquet?
Il est utile de créer une interface utilisateur Play/Stop/Pause lors de l'exécution avec un débogueur attaché, mais permet également au service Windows d'être installé et exécuté par l'environnement Windows Services. Tout cela avec une seule ligne de code! Qu'est-ce que Service Helper? Étant une personne qui écrit beaucoup de services Windows, il peut être frustrant de gérer les maux de tête liés au débogage des services. Cela implique souvent des astuces, des bidouilles et des solutions de contournement partielles pour tester l'ensemble de votre code. Il n’existe pas d’expérience "frapper simplement F5" pour les développeurs Windows Services.
Service Helper résout ce problème en déclenchant l'affichage d'une interface utilisateur si un débogueur est associé qui simule (aussi fidèlement que possible) l'environnement Windows Services.
Le projet github est ici: https://github.com/wolfen351/windows-service-gui
Comment utiliser?
Le moyen le plus simple d’obtenir Windows Service Helper dans votre projet est d’utiliser le package NuGet ServiceProcess.Helpers du flux officiel NuGet.
Modifiez simplement le code typique dans "Program.cs" pour votre application:
using System.ServiceProcess;
using ServiceProcess.Helpers; //HERE
namespace DemoService
{
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
//ServiceBase.Run(ServicesToRun);
ServicesToRun.LoadServices(); //AND HERE
}
}
}
Divulgation: Je suis le responsable de ce projet