J'ai écrit un service Windows qui expose un service WCF à une interface graphique installée sur le même ordinateur. Lorsque j'exécute l'interface graphique, si je ne peux pas me connecter au service, j'ai besoin de savoir si c'est parce que l'application de service n'a pas encore été installée, ou si c'est parce que le service n'est pas en cours d'exécution. Si l'ancien, je veux l'installer (comme décrit ici ); si ce dernier, je veux le démarrer.
La question est la suivante: comment détecter si le service est installé, puis comment l’avoir démarré après avoir été détecté?
Utilisation:
// add a reference to System.ServiceProcess.dll
using System.ServiceProcess;
// ...
ServiceController ctl = ServiceController.GetServices()
.FirstOrDefault(s => s.ServiceName == "myservice");
if(ctl==null)
Console.WriteLine("Not installed");
else
Console.WriteLine(ctl.Status);
Vous pouvez aussi utiliser ce qui suit.
using System.ServiceProcess;
...
var serviceExists = ServiceController.GetServices().Any(s => s.ServiceName == serviceName);
Boucle en fait comme ça:
foreach (ServiceController SC in ServiceController.GetServices())
peut générer une exception Accès refusé si le compte sous lequel votre application est en cours d'exécution ne dispose pas des droits pour afficher les propriétés du service. Par contre, vous pouvez le faire en toute sécurité même s’il n’existe aucun service portant ce nom:
ServiceController SC = new ServiceController("AnyServiceName");
Mais l'accès à ses propriétés si le service n'existe pas entraînera une exception InvalidOperationException. Voici donc un moyen sûr de vérifier si un service est installé:
ServiceController SC = new ServiceController("MyServiceName");
bool ServiceIsInstalled = false;
try
{
// actually we need to try access ANY of service properties
// at least once to trigger an exception
// not neccessarily its name
string ServiceName = SC.DisplayName;
ServiceIsInstalled = true;
}
catch (InvalidOperationException) { }
finally
{
SC.Close();
}
Pour les non-linq, vous pouvez simplement parcourir le tableau comme ceci:
using System.ServiceProcess;
bool serviceExists = false
foreach (ServiceController sc in ServiceController.GetServices())
{
if (sc.ServiceName == "myServiceName")
{
//service is found
serviceExists = true;
break;
}
}
private bool ServiceExists(string serviceName)
{
ServiceController[] services = ServiceController.GetServices();
var service = services.FirstOrDefault(s => string.Equals(s.ServiceName, serviceName, StringComparison.OrdinalIgnoreCase));
return service != null;
}
Je pense que c'est la meilleure réponse à cette question. Il n'est pas nécessaire d'ajouter un traitement supplémentaire pour vérifier si le service existe, car il lève une exception s'il ne le fait pas. Vous avez juste besoin de l'attraper. Vous n'avez pas non plus besoin de fermer () la connexion si vous enveloppez toute la méthode en utilisant ().
using (ServiceController sc = new ServiceController(ServiceName))
{
try
{
if (sc.Status != ServiceControllerStatus.Running)
{
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 10));
//service is now Started
}
else
//Service was already started
}
catch (System.ServiceProcess.TimeoutException)
{
//Service was stopped but could not restart (10 second timeout)
}
catch (InvalidOperationException)
{
//This Service does not exist
}
}