programing

.NET Windows Service OnStart 메서드를 디버깅하는 방법은 무엇입니까?

luckcodes 2021. 1. 17. 11:30

.NET Windows Service OnStart 메서드를 디버깅하는 방법은 무엇입니까?


Windows 서비스로 설치할 때만 실패하는 .NET으로 작성된 코드가 있습니다. 실패로 인해 서비스가 시작되지 않습니다. OnStart 메서드를 어떻게 사용할 수 있는지 알 수 없습니다.

방법 : Windows 서비스 응용 프로그램 디버그 는 다음과 같은 흥미로운 단서를 제공합니다.

서비스 프로세스에 연결하면 서비스 코드 전체가 아닌 대부분을 디버깅 할 수 있습니다. 예를 들어 서비스가 이미 시작 되었기 때문에 이러한 방식으로 서비스의 OnStart 메서드에있는 코드 나 서비스를로드하는 데 사용되는 Main 메서드에있는 코드를 디버깅 할 수 없습니다. 이 문제를 해결하는 한 가지 방법은 디버깅을 지원하기 위해서만 존재하는 서비스 응용 프로그램에 임시 두 번째 서비스를 만드는 것입니다. 두 서비스를 모두 설치 한 다음이 "더미"서비스를 시작하여 서비스 프로세스를로드 할 수 있습니다. 임시 서비스가 프로세스를 시작하면 Visual Studio의 디버그 메뉴를 사용하여 서비스 프로세스에 연결할 수 있습니다.

그러나 서비스 프로세스를로드하기 위해 더미 서비스를 생성해야하는 것이 정확히 어떻게되어 있는지 확실하지 않습니다.


임시 해결 방법으로 할 수있는 한 가지는 OnStart의 첫 번째 코드 줄로 디버거를 시작하는 것입니다.

System.Diagnostics.Debugger.Launch()

사용할 디버거를 묻는 메시지가 표시됩니다. Visual Studio에서 이미 솔루션을 열고 목록에서 해당 인스턴스를 선택하기 만하면됩니다.


나는 다음과 같은 방법을 추가하는 경향이 있습니다.

    [Conditional("DEBUG")]
    private void AttachDebugger()
    {
        Debugger.Break();
    }

프로젝트의 디버그 빌드에서만 호출되며 실행을 일시 중지하고 디버거를 연결할 수 있습니다.


를 사용하여 설치된 서비스가 있으면 서비스가 시작되면 디버거로 이동하도록을 installutil.exe변경할 수 있습니다 Start Parameters.

여기에 이미지 설명 입력

매개 변수 -debugWithVisualStudio(또는 단순히 -d)를 사용 하여 서비스를 수동으로 시작 하면 자동으로 올바른 프로젝트를 감지하고 Visual Studio에서 대화 형 디버거를 시작합니다.

여기에 이미지 설명 입력

이 기능을 지원하려면 서비스 기능을 변경하십시오 OnStart().

/// <summary>
///     Executed when the service is started.
/// </summary>
/// <param name="args">Command line arguments.</param>
protected override void OnStart(string[] args)
{
    try
    {
        //How to debug when running a Windows Service:
        // 1. Right click on the service name in Windows Service Manager.
        // 2. Select "Properties".
        // 3. In "Start Parameters", enter "-d" (or "-debugWithVisualStudio").
        // 4. Now, when you start the service, it will fire up Visual Studio 2012 and break on the line below.
        // 5. Make sure you have UAC (User Access Control) turned off, and have Administrator privileges.
#if DEBUG
        if (((ICollection<string>)args).Contains("-d")
            || ((ICollection<string>)args).Contains("-debugWithVisualStudio"))
        {
            Debugger.Launch(); // Launches VS2012 debugger.
        }
#endif
        ShellStart(args);
        base.OnStart(args);
    }
    catch (Exception ex)
    {
        // Log exception here.
    }
}

(선택 사항) 서비스에서 오류가 발생하는 정확한 코드 줄로 좁히려면 Visual Studio 메뉴에서 예외를 켭니다 DEBUG .. Exceptions. 디버깅을 계속하면 예외를 발생시키는 정확한 줄에서 중단됩니다.

여기에 이미지 설명 입력


잘 작동합니다!

protected override void OnStart(string[] args)
{
    System.Diagnostics.Debugger.Launch();
}

위의 옵션은 Windows 8에서 작동하지 않는 것 같습니다.

Thread.Sleep (15000); 추가했습니다. 내 OnStart () 메서드에 넣고 코드의 다음 줄에 중단 점을 설정합니다. 이렇게하면 서비스를 시작한 후 VS 디버거를 내 프로세스에 연결하는 데 15 초가 걸리고 OnStart () 메서드를 멋지게 디버깅 할 수 있습니다.


다음과 같은 코드 줄을 추가 할 수 있습니다.

System.Diagnostics.Debugger.Break()

그러면 디버그에 사용할 디버거를 선택하라는 창이 나타납니다. 예를 들어 Visual Studio에 연결하고 코드를 실행할 수 있습니다.

보다:

http://msdn.microsoft.com/en-us/library/system.diagnostics.debugger.break.aspx


콘솔 앱으로 실행되지만 리플렉션을 사용하여 서비스 메서드에 액세스하는 Windows 서비스에 대한 동반 프로젝트를 설정할 수 있습니다. 자세한 내용과 예는 여기를 참조하십시오 : http://ryan.kohn.ca/articles/how-to-debug-a-windows-service-in-csharp-using-reflection/ .


Service OnStart 메서드에서 다음 코드를 사용하십시오.

System.Diagnostics.Debugger.Launch();

팝업 메시지에서 Visual Studio 옵션을 선택합니다. Visual Studio를 관리자로 실행해야합니다.

참고 : 디버그 모드에서만 사용하려면 다음과 같이 #if DEBUG 컴파일러 지시문을 사용할 수 있습니다. 이렇게하면 프로덕션 서버의 릴리스 모드에서 우발적이거나 디버깅이 방지됩니다.

#if DEBUG
    System.Diagnostics.Debugger.Launch();
#endif

다른 사람들이 지적했듯이 OnStart-Method에 디버거 중단을 추가해야합니다.

#if DEBUG
    System.Diagnostics.Debugger.Break()
#endif

또한 VisualStudio를 관리자로 시작하고 다른 사용자가 프로세스를 자동으로 디버깅 할 수 있도록 허용합니다 ( 여기에 설명 됨 ).

reg add "HKCR\AppID\{E62A7A31-6025-408E-87F6-81AEB0DC9347}" /v AppIDFlags /t REG_DWORD /d 8 /f

(또한 여기에서 설명했습니다 : https://stackoverflow.com/a/35715389/5132456 )


늦었다는 것을 알고 있지만 이것이 Windows 서비스 디버깅을 처리하는 방법입니다.

먼저 서비스 역할을 할 클래스를 만듭니다.

시작, 중지, 일시 중지 등에 적절한 방법을 추가합니다.

서비스 프로젝트에 Windows 양식을 추가하십시오.

서비스 코드에서 위에서 만든 서비스 클래스를 만들고 ServiceBase 클래스에서 서비스를 시작 및 중지하는 데 필요한 호출을 수행합니다.

Program.cs를 열고 다음을 추가하십시오.

#if DEBUG
    [STAThread]
#endif
    static void Main()
    {
try
        {
#if DEBUG
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new DebugForm());
#else
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] 
        { 
            new YourWindowsService() 
        };
            ServiceBase.Run(ServicesToRun);
#endif
        }
        catch (Exception e)
        {
            logger.Error(DateTime.Now.ToString() + " - " + e.Source + " - " + e.ToString() + "\r\n------------------------------------\r\n");
        }
}

DEBUG 모드에서 실행하면 Windows 양식이 시작됩니다. 완료되면 릴리스 모드에서 빌드하는 것을 잊지 마십시오. 물론 조건부 컴파일 변수는 원하는 모든 것이 될 수 있습니다. 디버그 양식이 자체 프로젝트가되도록 별도의 프로젝트를 만들 수도 있습니다.

도움이 되었기를 바랍니다


System.Diagnostics.Debugger.Launch () 메서드를 사용해 볼 수도 있습니다 . 디버거 포인터를 지정된 위치로 가져가는 데 도움이되며 코드를 디버깅 할 수 있습니다.

이 단계 전에 Visual Studio 명령 프롬프트의 명령 줄 -installutil projectservice.exe를 사용 하여 service.exe를 설치하십시오.

그런 다음 제어판-> 관리 도구-> 컴퓨터 관리-> 서비스 및 응용 프로그램-> 서비스-> 서비스 이름에서 서비스를 시작합니다.


OnStart 메서드에 Debugger.Launch ()를 추가했는데 작동하지 않으면 생성자에서 예외가 발생하여 OnStart가 호출되지 않은 것과 같은 문제가 발생할 수 있습니다. (헤드 슬랩)

(이게 다른 사람의 답변에 대한 의견 이었어 야한다면 미안하지만 의견을 낼 수있는 충분한 신용이 없습니다.)


문제가있는 메서드 안에 Debugger.Break를 추가해보세요. 서비스가 시작되면 예외가 발생하고 미망인은 Visual Studio를 사용하여 디버그를 제안해야합니다.


일반적으로 SCM 인 것처럼 가장하는 콘솔 앱이 있습니다. 예를 들어 Start, Stop을 호출 한 다음 주요 코딩 / 디버깅 목적으로 F5를 호출하고 Debugger.Break를 사용하여 서비스가 설치되고 SCM.

It means a bit more work to start with, I have a class lib that contains all the service code, with a class that exposes Start and Stop that the Windows Service class and the console app can both call.

Matt


Before I go in the topic one advise. Always use log specially if you are server side developer. Because there are some certain condition which you might not be able to produce while debugging the code in visual studio.

Coming back to topic, I use Envoirnment.UserInteractive flag this is really handy see my code below

public static void Main(string[] args)
{

    if (System.Environment.UserInteractive)
    {
        string parameter = string.Concat(args);

        switch (parameter)
        {
            case "--install":
                ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });
                break;
            case "--uninstall":
                ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
                break;
            default:
                WindowsService service = new WindowsService();
                service.OnStart(args);
                Console.ReadKey();
                service.OnStop();
                break;
        }
    }
    else
    {
        ServiceBase.Run(new WindowsService());
    }
}

From visual studio you will get UserInteractive flag set so i would run it as console application, In addition to that even you can run product build by double clicking it and attaching debugger with it if you like to test it.


I have an interesting way of doing this I add another Configuration called DebugNoService

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugNoService|AnyCPU' ">
    <OutputPath>.\</OutputPath>
    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
    <BaseAddress>285212672</BaseAddress>
    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
    <ConfigurationOverrideFile>
    </ConfigurationOverrideFile>
    <DefineConstants>DEBUG;TRACE;DEBUGNOSERVICE</DefineConstants>
    <DocumentationFile>
    </DocumentationFile>
    <DebugSymbols>true</DebugSymbols>
    <FileAlignment>4096</FileAlignment>
    <NoStdLib>false</NoStdLib>
    <NoWarn>
    </NoWarn>
    <Optimize>false</Optimize>
    <RegisterForComInterop>false</RegisterForComInterop>
    <RemoveIntegerChecks>false</RemoveIntegerChecks>
    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
    <WarningLevel>4</WarningLevel>
    <DebugType>full</DebugType>
    <ErrorReport>prompt</ErrorReport>
    <UseVSHostingProcess>false</UseVSHostingProcess>
  </PropertyGroup>

#if 지시문을 사용합니다. ProjectInstaller.cs

#if !DEBUGNOSERVICE    
   static void Main()
   {
      System.ServiceProcess.ServiceBase[] ServicesToRun;
      .....
   }
#endif

나는 윈도우 폼을 추가하고 윈도우 폼을

#if DEBUGNOSERVICE
...
static void Main() 
{
    Form     form;

    Application.EnableVisualStyles();
    Application.DoEvents();

    form = new <the name of the form>();

    Application.Run(form);
}
...
#endif

선택한 구성에 따라 코드는 쉽게 디버깅 할 수있는 Windows 양식 응용 프로그램 또는 서비스로 실행됩니다.

많은 작업처럼 보이지만 항상 작동하고 코드 디버깅을 매우 쉽게 만듭니다. 양식에 모든 종류의 출력을 추가하여 실행되는 것을 볼 수 있습니다.

참조 URL : https://stackoverflow.com/questions/1196531/how-to-debug-the-net-windows-service-onstart-method