web-dev-qa-db-ja.com

.NET WindowsサービスのOnStartメソッドをデバッグする方法は?

Windowsサービスとしてインストールした場合にのみ失敗する.NETで記述されたコードがあります。失敗すると、サービスを開始することさえできません。 OnStartメソッドにステップインする方法を理解できません。

方法:Windowsサービスアプリケーションをデバッグするは興味をそそる手がかりを与えます:

サービスのプロセスにアタッチすると、サービスのすべてのコードではなく、ほとんどのコードをデバッグできます。たとえば、サービスは既に開始されているため、この方法でサービスのOnStartメソッドのコードをデバッグしたり、サービスの読み込みに使用されるMainメソッドのコードをデバッグしたりすることはできません。 これを回避する1つの方法は、デバッグを支援するためだけに存在する一時的な2番目のサービスをサービスアプリケーションに作成することです。両方のサービスをインストールし、この「ダミー」サービスを開始してサービスプロセスをロードできます。一時的なサービスがプロセスを開始したら、Visual Studioの[デバッグ]メニューを使用してアタッチできます。サービスプロセスに。

ただし、サービスプロセスをロードするためにダミーサービスを作成することになっていることが正確にはわかりません。

52
Nathan

一時的な回避策としてできることの1つは、OnStartのコードの最初の行としてデバッガーを起動することです。

System.Diagnostics.Debugger.Launch()

これにより、使用するデバッガの入力が求められます。ソリューションをVisual Studioで既に開いて、リストからそのインスタンスを選択するだけです。

96
palehorse

私はこのようなメソッドを追加する傾向があります:

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

プロジェクトのデバッグビルドでのみ呼び出され、実行を一時停止し、デバッガーをアタッチできるようにします。

10
SpaceghostAli

_installutil.exe_を使用してインストールされたサービスを取得したら、_Start Parameters_を変更して、サービスが開始された場合にデバッガーにジャンプできます。

enter image description here

パラメーター_-debugWithVisualStudio_(または単に_-d_)を使用して手動でサービスを開始すると、自動的に正しいプロジェクトが検出され、Visual Studioで対話型デバッガーが起動します。

enter image description here

この機能をサポートするには、サービスの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_から例外をオンにします。デバッグを続行すると、例外をスローしている正確な行で中断します。

enter image description here

8
Contango

それはうまくいきます!

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

上記のオプションは、Windows 8では機能しないようです。

Thread.Sleep(15000);を追加しました。 OnStart()メソッドに追加し、コードの次の行にブレークポイントを設定します。これにより、サービスを開始してからVSデバッガーをプロセスにアタッチするのに15秒かかり、OnStart()メソッドをうまくデバッグできました。

5
Boris Hurinek

次のようなコード行を追加できます。

System.Diagnostics.Debugger.Break()

これにより、デバッグに使用するデバッガーを選択するよう求めるウィンドウが表示されます。 Visual Studioでアタッチしてコードにステップインできます。

見る:

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

4
Alex Black

他の人が指摘しているように、デバッガーブレークをOnStartメソッドに追加する必要があります。

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

また、管理者としてVisualStudioを起動し、別のユーザーがプロセスを自動的にデバッグできるようにします(説明: here ):

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

(ここでも説明しました: https://stackoverflow.com/a/35715389/5132456

2
wotanii

Service OnStartメソッドで次のコードを使用します。

System.Diagnostics.Debugger.Launch();

ポップアップメッセージからVisual Studioオプションを選択します。 Visual Studioを管理者として実行することを忘れないでください。

注:デバッグモードでのみ使用するには、次のように#if DEBUGコンパイラディレクティブを使用できます。これにより、実稼働サーバーでのリリースモードでの偶発的またはデバッグを防ぎます。

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

コンソールアプリとして実行されるWindowsサービスのコンパニオンプロジェクトを設定できますが、Reflectionを使用してサービスメソッドにアクセスします。詳細と例については、こちらをご覧ください: http://ryan.kohn.ca/articles/how-to-debug-a-windows-service-in-csharp-using-reflection/

2
Ryan Kohn

私はこれが遅いことを知っていますが、これは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フォームが起動します。終了したら、リリースモードでビルドすることを忘れないでください。もちろん、条件付きコンパイル変数は好きなものにできます。デバッグフォームが独自のプロジェクトになるように、別のプロジェクトを作成することもできます。

お役に立てれば

1
Coach David

System.Diagnostics.Debugger.Launch()メソッドを試すこともできます。指定した場所へのデバッガーポインターを取得するのに役立ち、コードをデバッグできます。

この手順の前にservice.exeをインストールしてください Visual Studioコマンドプロンプトのコマンドラインを使用してください-installutil projectservice.exe

次に、コントロールパネル->管理ツール->コンピューターの管理->サービスとアプリケーション->サービス->サービス名からサービスを開始します。

1

OnStartメソッドにDebugger.Launch()を追加しても機能しない場合は、コンストラクターで例外が発生していたため、OnStartが呼び出されないという同じ問題が発生する可能性があります。 (ヘッドスラップ)

(これが他の誰かの答えに対するコメントでなければならない場合は申し訳ありませんが、コメントするのに十分な信用を持っていません)

1
and... break

問題のあるメソッド内にDebugger.Breakを追加してみてください。サービスが開始されると、例外がスローされ、未亡人はVisual Studioを使用してデバッグを提供する必要があります。

0
Dror Helper

私は通常、SCMのふりをするコンソールアプリを持っています。 Start、Stopを呼び出して、メインのコーディング/デバッグの目的でF5キーを押し、SCMを介してサービスがインストールおよび開始されたら、Debugger.Breakを使用してデバッグします。

開始するにはもう少し作業が必要です。すべてのサービスコードを含むクラスライブラリと、Windowsサービスクラスとコンソールアプリの両方が呼び出すことができるStartとStopを公開するクラスがあります。

マット

0
Matt

トピックに進む前に、アドバイスをお願いします。サーバー側の開発者の場合は、常にログを特別に使用してください。 Visual Studioでコードのデバッグ中に生成できない特定の条件があるためです。

トピックに戻って、Envoirnment.UserInteractiveフラグを使用します。これは本当に便利です。以下のコードを参照してください

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

Visual StudioからUserInteractiveフラグを設定してコンソールアプリケーションとして実行します。さらに、テストする場合は、ダブルクリックしてデバッガーをアタッチすることで、製品ビルドを実行することもできます。

0
Mubashar

これを行う興味深い方法があります。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

Windowsフォームを追加し、Windowsフォームをラップします

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

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

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

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

選択した構成に応じて、コードは、簡単にデバッグできるWindowsフォームアプリケーションまたはサービスとして実行されます。

Ifは多くの作業のように思えますが、常に機能しており、コードのデバッグが非常に簡単になります。あらゆる種類の出力をフォームに追加して、実行を監視できます。

0
M pollack