同じマシンにインストールされたGUIにWCFサービスを公開するWindowsサービスを作成しました。 GUIを実行するときに、サービスに接続できない場合は、サービスアプリがまだインストールされていないためか、サービスが実行されていないためかを知る必要があります。前者の場合、それをインストールします(説明したとおり here )。後者の場合は、起動します。
質問:サービスがインストールされているかどうかをどのように検出し、インストールされていることを検出したら、どのように起動しますか?
つかいます:
// 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);
以下も使用できます。
using System.ServiceProcess;
...
var serviceExists = ServiceController.GetServices().Any(s => s.ServiceName == serviceName);
実際には次のようにループします:
foreach (ServiceController SC in ServiceController.GetServices())
アプリケーションを実行しているアカウントにサービスプロパティを表示する権限がない場合、アクセス拒否例外がスローされる場合があります。一方、そのような名前のサービスが存在しない場合でも、これを安全に行うことができます。
ServiceController SC = new ServiceController("AnyServiceName");
ただし、サービスが存在しない場合にプロパティにアクセスすると、InvalidOperationExceptionが発生します。サービスがインストールされているかどうかを確認する安全な方法は次のとおりです。
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();
}
非linqの場合、次のように配列を反復処理するだけです。
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;
}
これがこの質問に対する最良の答えだと思います。サービスが存在しない場合は例外をスローするため、サービスが存在するかどうかを確認するために特別な処理を追加する必要はありません。キャッチするだけです。また、using()でメソッド全体をラップする場合、接続を閉じる()必要はありません。
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
}
}