2010-03-25 2 views
23

C#으로 작성된 서비스를 디버깅하고 싶습니다. 구식 방식은 너무 길어요. 서비스를 중지하고 디버그 모드 (Visual studio 2008)에서 서비스를 사용하는 응용 프로그램을 시작하고 서비스를 시작한 다음 서비스 프로세스에 연결 한 다음 내 Asp.Net 응용 프로그램을 탐색하여 서비스를 트리거해야합니다.콘솔 앱에 C# 서비스를 배치하여 디버깅하십시오.

기본적으로 서비스를 백그라운드에서 실행 중이며 작업을 기다리고 있습니다. 웹 응용 프로그램은 서비스에서 수행 할 작업을 트리거합니다. 내가하고 싶은 무엇

디버그에 나를 위해 노력 서비스를 발사 콘솔 응용 프로그램을하는 것입니다. 아무도 모르는 간단한 데모가 있습니까?

는 잭 여기

답변

1

는 콘솔 응용 프로그램으로 당신의 Windows 서비스를 실행에 대한 blog post 감사합니다.

또한 단지 방법을 테스트하는 서비스로 같은 논리를 참조하거나 서비스 '논리에 단위 테스트를 설정 새 콘솔 응용 프로그램을 만들 수

1

나는 어려운 설정을 디버깅하는 단위 테스트를 사용했다 과거에는 단위 테스트에 디버깅 중단 점을 설정하고 매개 변수가있는 서비스 메서드를 호출하는 단위 테스트를 작성하십시오.

testdriven.net 또는 jetbrains testrunner를 사용하면 쉽게 사용할 수 있습니다. 디버그 빌드에 대한

2

는 내가 설정 설정 중 하나를하거나 지시를 사용하는 경향이 :

#if DEBUG 
    Debugger.Break(); 
#endif 

또는

if(Settings.DebugBreak) 
      Debugger.Break(); 

내가 넣어 그 서비스 구성 요소의 ONSTART 방법. 그런 다음 자동으로 프롬프트되고 프로세스에 연결됩니다.

20

당신은 주 진입 점에서이 같은 작업을 수행 할 수 있습니다

static void Main() 
{ 
#if DEBUG 
    Service1 s = new Service1(); 
    s.Init(); // Init() is pretty much any code you would have in OnStart(). 
#else 
    ServiceBase[] ServicesToRun; 
    ServicesToRun=new ServiceBase[] 
    { 
     new Service1() 
    }; 
    ServiceBase.Run(ServicesToRun); 
#endif 
} 

하고 ONSTART 이벤트 핸들러 :

protected override void OnStart(string[] args) 
{ 
    Init(); 
} 
+0

+1 - 나는 내가 작성한 몇 가지 서비스에서 거의 동일한 코드를 가지고 있습니다. – 37Stars

15

접근 방식의 I 항상 취해야 할 것은 모든 응용 프로그램을 격리하는 것입니다. 클래스의 로직을 클래스 라이브러리에 추가 할 수 있습니다. 이렇게하면 서비스 프로젝트가 실제로 클래스 라이브러리를 서비스로 호스트하는 셸이됩니다. 이렇게함으로써

, 당신은 쉽게 단위 테스트와 프로세스에 연결하여 서비스를 디버깅의 두통을 처리하지 않고, 코드를 디버깅합니다. 물론 단위 테스트를 권하고 싶지만 그렇게하지 않으면 서비스와 동일한 진입 점을 호출하는 콘솔 애플리케이션을 추가하는 것이 좋습니다.

3

TopShelf이 방법에 가장 적합한 또 다른 프로젝트입니다. 프로세스를 서비스로 실행하거나 최소한의 구성으로 일반 콘솔 응용 프로그램으로 실행할 수 있습니다.

10

전역 정의를 사용하지 않으려면 일반적으로 Environment.UserInteractive 속성을 통해 서비스 또는 일반 응용 프로그램인지 여부를 런타임에 테스트합니다.

[MTAThread()] 
    private static void Main() 
    { 
     if (!Environment.UserInteractive) 
     { 
      ServiceBase[] aServicesToRun; 

      // More than one NT Service may run within the same process. To add 
      // another service to this process, change the following line to 
      // create a second service object. For example, 
      // 
      // ServicesToRun = New System.ServiceProcess.ServiceBase() {New ServiceMain, New MySecondUserService} 
      // 
      aServicesToRun = new ServiceBase[] {new ServiceMain()}; 

      Run(aServicesToRun); 
     } 
     else 
     { 
      var oService = new ServiceMain(); 
      oService.OnStart(null); 
     } 
    } 
+8

콘솔을 표시하려면 프로젝트 속성에서 출력 유형을 콘솔 응용 프로그램으로 설정하는 것을 잊지 마십시오. 이 프로그램은 콘솔 응용 프로그램인지 Windows 응용 프로그램인지에 관계없이 Windows 서비스로 계속 실행할 수 있으므로 걱정하지 마십시오. –

0

내 프로세스가 서비스로 실행 중인지 확인하려면이 방법을 사용합니다.

public class ServiceDiagnostics 
{ 
    readonly bool _isUserService; 
    readonly bool _isLocalSystem; 
    readonly bool _isInteractive; 

    public ServiceDiagnostics() 
    { 
     var wi = WindowsIdentity.GetCurrent(); 
     var wp = new WindowsPrincipal(wi); 

     var serviceSid = new SecurityIdentifier(WellKnownSidType.ServiceSid, null); 
     var localSystemSid = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null); 
     var interactiveSid = new SecurityIdentifier(WellKnownSidType.InteractiveSid, null); 

     this._isUserService = wp.IsInRole(serviceSid); 

     // Neither Interactive or Service was present in the current user's token, This implies 
     // that the process is running as a service, most likely running as LocalSystem. 
     this._isLocalSystem = wp.IsInRole(localSystemSid); 

     // This process has the Interactive SID in its token. This means that the process is 
     // running as a console process. 
     this._isInteractive = wp.IsInRole(interactiveSid); 
    } 

    public bool IsService 
    { 
     get { return this.IsUserService || this.IsLocalSystem || !this.IsInteractive; }  
    } 

    public bool IsConsole 
    { 
     get { return !this.IsService; } 
    } 

    /// <summary> 
    /// This process has the Service SID in its token. This means that the process is running 
    /// as a service running in a user account (not local system). 
    /// </summary> 
    public bool IsUserService 
    { 
     get { return this._isUserService; } 
    } 

    /// <summary> 
    /// Neither Interactive or Service was present in the current user's token, This implies 
    /// that the process is running as a service, most likely running as LocalSystem. 
    /// </summary> 
    public bool IsLocalSystem 
    { 
     get { return this._isLocalSystem; } 
    } 

    /// <summary> 
    /// This process has the Interactive SID in its token. This means that the process is 
    /// running as a console process. 
    /// </summary> 
    public bool IsInteractive 
    { 
     get { return this._isInteractive; } 
    } 
} 
2

아래와 같이 리플렉션을 통해 서비스 메소드를 호출 할 수 있습니다.

Environment.UserInteractive을 사용하면 우리가 콘솔 앱으로 또는 서비스로 실행 중인지 알 수 있습니다.

ServiceBase[] ServicesToRun; 
ServicesToRun = new ServiceBase[] 
{ 
    new MyService() 
}; 

if (!Environment.UserInteractive) 
{ 
    // This is what normally happens when the service is run. 
    ServiceBase.Run(ServicesToRun); 
} 
else 
{ 
    // Here we call the services OnStart via reflection. 
    Type type = typeof(ServiceBase); 
    BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; 
    MethodInfo method = type.GetMethod("OnStart", flags); 

    foreach (ServiceBase service in ServicesToRun) 
    { 
     Console.WriteLine("Running " + service.ServiceName + ".OnStart()"); 
     // Your Main method might not have (string[] args) but you could add that to be able to send arguments in. 
     method.Invoke(service, new object[] { args }); 
    } 

    Console.WriteLine("Finished running all OnStart Methods."); 

    foreach (ServiceBase service in ServicesToRun) 
    { 
     Console.WriteLine("Running " + service.ServiceName + ".OnStop()"); 
     service.Stop(); 
    } 
} 
관련 문제