2010-12-29 7 views
64

동일한 컴퓨터에 설치된 GUI에 WCF 서비스를 제공하는 Windows 서비스를 작성했습니다. GUI를 실행할 때 서비스에 연결할 수 없으면 서비스 응용 프로그램이 아직 설치되지 않았거나 서비스가 실행되고 있지 않아서인지 여부를 알아야합니다. 전자의 경우, 나는 그것을 설치하고 싶을 것이다. (here을 보라); 후자라면, 나는 그것을 시작하고 싶을 것이다.Windows 서비스가 C#에 설치되어 있는지 확인하는 방법

질문 : 서비스가 설치되어 있는지 감지하고 어떻게 설치되어 있는지 감지하면 어떻게 시작합니까?

답변

116

사용 :

// 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); 
+0

+1 재미있는 ... –

+0

감사합니다 - 내가 필요로 그냥 뭐! –

+1

+1 화려한! 그리고 고마워. –

27

당신은뿐만 아니라 다음 사용할 수 있습니다 .. 비 LINQ를 들어

using System.ServiceProcess; 
... 
var serviceExists = ServiceController.GetServices().Any(s => s.ServiceName == serviceName); 
+1

IMO는 서비스가 있는지 확인하는 가장 우아한 방법입니다. Linq의 힘을 이용하여 단 한 줄의 코드. 그런데, .Any()는 예/아니오 질문을 할 때 원하는 바를 정확하게 반환합니다 :-) –

+0

원격 컴퓨터에서 서비스를 확인하려면 ['GetServices (string)'] (https://msdn.microsoft.com/en-us/library/s21fd6th.aspx) – ShooShoSha

2

, 당신은 단지 같은 배열을 통해 반복 할 수

using System.ServiceProcess; 

bool serviceExists = false 
foreach (ServiceController sc in ServiceController.GetServices()) 
{ 
    if (sc.ServiceName == "myServiceName") 
    { 
     //service is found 
     serviceExists = true; 
     break; 
    } 
} 
2

실제로 루핑은 다음과 같습니다.

foreach (ServiceController SC in ServiceController.GetServices()) 

은 응용 프로그램이 실행중인 계정에 서비스 속성을 볼 수있는 권한이없는 경우 액세스가 거부 된 예외를 throw 할 수 있습니다. 반면에, 당신은 안전하게 같은 이름을 가진 서비스가 존재하지 않는 경우에도이 작업을 수행 할 수 있습니다

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(); 
} 
+0

감사합니다! 끝내기를 원하십니까? finally { SC.Close(); } – Cel

+2

전체를 포장하여 사용하는 것이 어떻습니까? using 문이 자동으로 처리되므로 마침내 {SC.Close()}의 필요성이 제거됩니다. using (ServiceController SC = new ServiceController ("MyServiceName")) – bill

0

I는이 질문에 대한 가장 좋은 대답라고 생각합니다. 서비스가 존재하는지 확인하기 위해 별도의 처리를 추가 할 필요가 없습니다. 서비스가 존재하지 않는 경우 예외를 throw하므로 서비스가 존재하는지 확인하십시오. 당신은 단지 그것을 잡을 필요가 있습니다. 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  
}  
} 
+0

전혀 좋은 답변이 아닙니다.(1) 예외로 코드를 관리하는 것은 매우 비효율적이며 비효율적이며 느립니다. (2) 허용 된 대답은 간결하고 간결하며 요구 사항에 완벽하게 응답합니다. 당신은 당신 자신의 대답으로 잠수하기 전에 그것을 보았습니까? –

+0

분명히 대답을 읽는 법을 알지 못하는 것 같습니다. 원래 대답에 포함되지 않은 서비스를 시작하는 방법을 명확하게 물었 기 때문입니다. – bill

+0

분명히 코드를 올바르게 작성하는 방법을 알지 못합니다. @Shaul Behr이 이미 언급했듯이 비효율적이며 느리기 때문에 접근 방법이 좋지 않습니다. 귀하의 _ 답변을 말하는 것은 아마도 최고이며, 심지어 더 나빠집니다 : 자기 찬양은 SO (그리고 아마 전 세계에 걸쳐)에서 좋은 행동으로 간주되지 않습니다. – Yoda

1
private bool ServiceExists(string serviceName) 
    { 
     ServiceController[] services = ServiceController.GetServices(); 
     var service = services.FirstOrDefault(s => string.Equals(s.ServiceName, serviceName, StringComparison.OrdinalIgnoreCase)); 
     return service != null; 
    } 
관련 문제