Windowsサービスをデバッグするより簡単な方法


325

Windowsサービスコントロールマネージャーからサービスを開始して、デバッガーをスレッドにアタッチするよりも、コードをステップ実行する簡単な方法はありますか?それはちょっと厄介で、もっと簡単な方法があるのか​​と思っています。


このユーザーボイスチケットを作成しました。それのために投票を考えてみましょう:visualstudio.uservoice.com/forums/121579-visual-studio-ide/...
デヴィッド・

回答:


271

サービスをすばやくデバッグしたい場合はDebugger.Break()、そこに立ち寄ります。その行に到達すると、VSに戻ります。完了したら、その行を削除することを忘れないでください。

更新:#if DEBUGプラグマの代わりに、Conditional("DEBUG_SERVICE")属性を使用することもできます。

[Conditional("DEBUG_SERVICE")]
private static void DebugMode()
{
    Debugger.Break();
}

OnStart、このメソッドを呼び出すだけです:

public override void OnStart()
{
     DebugMode();
     /* ... do the rest */
}

そこでは、コードはデバッグビルド中にのみ有効になります。その間、サービスのデバッグ用に個別のビルド構成を作成すると便利な場合があります。


45
または、Debugger.Launch()を使用して、Systems.Diagnostics名前空間のusingステートメントを含める必要があります。
Omar Kooheji 2008

1
あなたのブログ投稿はうまくいき、私の日を救いました:) Debugger.Break()は私のために働きませんでした。.Netは、いくつかの最適化関連の理由でDebugMode関数をスキップするようです。
ビザン

3
Debugger.Launch()は、Debugger.Break()が機能しない場合に機能します。(プロセスはコード255で終了します。)
Oliver Bock

どうやってこれを機能させるの?何も起こりません。私はBreak()とLaunch()を試しました。
4thSpace 2016年

13
@ 4thSpace:1.サービスのインストーラーを作成して、サービスをインストールできるようにします。2. Debugger.Launch();という行を追加します。Main()の先頭。3.デバッグモードでコードをビルドします。4.インストールされているdllをdebug-dllで上書きします。5. Windowsサービスパネルからサービスを開始します。デバッガーに接続するように求めるポップアップが表示されます。この方法でうまくいきました。うまくいけばあなたにも。
ffonz

210

また、通常の実行とサービスとして別の「バージョン」を使用する方法もあると思いますが、その目的のために別のコマンドラインスイッチを専用にする必要がありますか?

あなただけではできませんでした:

public static int Main(string[] args)
{
  if (!Environment.UserInteractive)
  {
    // Startup as service.
  }
  else
  {
    // Startup as application
  }
}

それには「メリット」があります。ダブルクリックでアプリを起動するだけで(本当に必要な場合はOK)F5、Visual Studioで(プロジェクトの設定を変更してその/consoleオプションを含める必要なく)実行できます。

技術的にはEnvironment.UserInteractiveWSF_VISIBLEフラグは現在のウィンドウステーションに設定されているかどうかをチェックしますがfalse、(非インタラクティブ)サービスとして実行される以外に、フラグが返される理由は他にありますか?


すごい!以前は「if #debug」メソッドを使用して、デバッグの場合はアプリケーションとして開始し、それ以外の場合はサービスとして開始しました。これにより、アプリをデバッグしたい場合にアプリがサービスとして実行できなくなりますが、ソリューションはこれを解決し、サービス/アプリとリリース/デバッグの4つの組み合わせすべてで実行できるようにします。
ジョナス

29
ダブルクリックしたときにプログラムを実行したくない場合(ユーザーが混乱して複数のインスタンスを実行するなど)、のSystem.Diagnostics.Debugger.IsAttached代わりにを使用できますEnvironment.UserInteractive
Blorgbeardは2010

5
(非インタラクティブ)サービスとして実行される以外に、falseを返す理由は他にありますか? 考えられるのは、コンソールに接続しないスケジュールされたタスクです。
ホーガン

7
この場合、コマンドラインパラメータを使用します。--installはサービスをインストールし、-uninstallはサービスをアンインストールし、-interactiveはサービスをアプリケーションとして実行します。プロジェクトオプションに--interactiveを追加します([デバッグ]> [コマンド引数])。したがって、VSから簡単にデバッグできます。--interactiveが必要なため、ダブルクリックしても不要な実行インスタンスは作成されません。ちょうど私の2セント。
EmirAkaydın

@EmirAkaydınはい、実際にコマンドラインパラメータも「バックアップ」として持っています。しかし、私は実際に望んでいたとき、ダブルクリックではなく、サービスが道ことを開始することができないという事実に関するエラーメッセージ「インタラクティブ」のインスタンスを持っています。さまざまな目標を私は推測します;-)
クリスチャン

123

数週間前に新しいサービスプロジェクトを立ち上げたときに、この投稿を見つけました。多くのすばらしい提案がありますが、私が望んでいた解決策はまだ見つかりませんでした。サービスクラスを変更せずにサービスクラスOnStartOnStopメソッドを呼び出す可能性。

私が思いついたソリューションは、Environment.Interactiveこの投稿の他の回答で示唆されているように、select実行モードを使用しています。

static void Main()
{
    ServiceBase[] servicesToRun;
    servicesToRun = new ServiceBase[] 
    {
        new MyService()
    };
    if (Environment.UserInteractive)
    {
        RunInteractive(servicesToRun);
    }
    else
    {
        ServiceBase.Run(servicesToRun);
    }
}

RunInteractiveヘルパーは、保護呼び出すためにリフレクションを使用OnStartしてOnStopメソッドを:

static void RunInteractive(ServiceBase[] servicesToRun)
{
    Console.WriteLine("Services running in interactive mode.");
    Console.WriteLine();

    MethodInfo onStartMethod = typeof(ServiceBase).GetMethod("OnStart", 
        BindingFlags.Instance | BindingFlags.NonPublic);
    foreach (ServiceBase service in servicesToRun)
    {
        Console.Write("Starting {0}...", service.ServiceName);
        onStartMethod.Invoke(service, new object[] { new string[] { } });
        Console.Write("Started");
    }

    Console.WriteLine();
    Console.WriteLine();
    Console.WriteLine(
        "Press any key to stop the services and end the process...");
    Console.ReadKey();
    Console.WriteLine();

    MethodInfo onStopMethod = typeof(ServiceBase).GetMethod("OnStop", 
        BindingFlags.Instance | BindingFlags.NonPublic);
    foreach (ServiceBase service in servicesToRun)
    {
        Console.Write("Stopping {0}...", service.ServiceName);
        onStopMethod.Invoke(service, null);
        Console.WriteLine("Stopped");
    }

    Console.WriteLine("All services stopped.");
    // Keep the console alive for a second to allow the user to see the message.
    Thread.Sleep(1000);
}

これが必要なすべてのコードですが、説明付きのウォークスルーも作成しました。


これは、ServiceBase []の適切な拡張メソッドになります。私のソリューションには複数のサービスがあるため、Program.csの共通の基本クラスではなく、servicesToRun.RunInteractive(args)を呼び出します。素晴らしいソリューション@Anders!
David Keaveny 2013

3
確かに素晴らしいソリューションです。:ダビデは、コードは1行だけでサービスを実行することを可能に示唆したように、私は[] ServiceBaseのための単純な拡張を作成しpastebin.com/F0fhhG2R
Funbit

4
+1以前の同僚が "EasyRunService"基本クラス(ServiceProcessを継承)を作成しましたが、これはほとんど同じことを行いますが、リフレクションの必要はありません(OnStartが基本クラスにあるため)。これにより、Windowsサービスのデバッグが非常に簡単になります。
ゾンダーガード、2015年

3
@ Chazt3nプロジェクトの出力タイプが「コンソールアプリケーション」に設定されていることを確認します。サービスのインストールについては、どの出力タイプを選択してもかまいません。動作は同じです。
Funbit 2016年

2
まだ素晴らしい解決策です!(に示すようにwalk through)追加するのは、Console Applicationコンパイルして実行する前に、プロジェクトのプロパティに移動し、出力タイプをに変更することだけです。で見つけてくださいProject Properties -> Application -> Output type -> Console Application。また、これが正しく機能するために、startコマンドを使用してアプリケーションを実行する必要がありました。例:C:\"my app name.exe" -service私にはうまくいきません。代わりに使用しましたC:\start /wait "" "my app name.exe" -service
Arvo Bowen

47

サービスの起動時に何が起こっているかを分析することが重要な場合があります。プロセスのアタッチはここでは役に立ちません。サービスの起動中にデバッガーをアタッチするのに十分な速さがないためです。

簡単に言えば、私はこれを行うために次の4行のコードを使用しています。

#if DEBUG
    base.RequestAdditionalTime(600000); // 600*1000ms = 10 minutes timeout
    Debugger.Launch(); // launch and attach debugger
#endif

これらはOnStart、次のようにサービスのメソッドに挿入されます。

protected override void OnStart(string[] args)
{
    #if DEBUG
       base.RequestAdditionalTime(600000); // 10 minutes timeout for startup
       Debugger.Launch(); // launch and attach debugger
    #endif
    MyInitOnstart(); // my individual initialization code for the service
    // allow the base class to perform any work it needs to do
    base.OnStart(args);
}

以前にそれを行ったことがない人のために、簡単に行き詰まる可能性があるため、以下詳細なヒントを含めました。次のヒントは、Windows 7x64およびVisual Studio 2010 Team Editionを指しますが、他の環境でも有効です。


重要:サービスを「手動」モードでデプロイしますInstallUtilVSコマンドプロンプトからユーティリティを使用するか、準備したサービスインストーラープロジェクトを実行します)。サービスを開始する前に Visual Studioを開き、サービスのソースコードを含むソリューションを読み込みます。VisualStudioで必要に応じて追加のブレークポイントを設定し、サービスコントロールパネルからサービスを開始します

そのためのDebugger.Launchコード、これはダイアログの原因となります「未処理のMicrosoft .NET Frameworkの例外が発生した中でServicename.exe。」現れる。スクリーンショットに示すようにクリックします。Elevate Yes, debug Servicename.exe
FrameworkException

その後、特にWindows 7では、UACが管理者の資格情報の入力を要求する場合があります。それらを入力して続行してYesください:

UACPrompt

その後、有名なVisual Studio Just-In-Time Debuggerウィンドウが表示されます。選択したデバッガを使用してデバッグするかどうかを尋ねます。あなたがクリックする前にYesあなたがすることを選択し、新しいインスタンスオープンにしたくない(第二オプション) -ソースコードが表示されないため、新しいインスタンスが、ここでは有用ではないでしょう。代わりに、先ほど開いたVisual Studioインスタンスを選択します。 VSDebuggerPrompt

をクリックYesした後、しばらくすると、Visual StudioによってDebugger.Launchステートメントのある行に黄色の矢印が表示され、コード(メソッドMyInitOnStart、初期化を含む)をデバッグできるようになります。 VSDebuggerBreakpoint

を押すとF5準備した次のブレークポイントに到達するまで、すぐに実行が続行されます。

ヒント:サービスの実行を継続するには、[ デバッグ]-> [すべて切り離す]を選択します。これにより、サービスが正しく起動し、起動コードのデバッグが終了した後で、サービスと通信するクライアントを実行できます。Shift+F5(デバッグを停止)を押すと、サービスが終了します。これを行う代わりに、サービスコントロールパネルを使用して停止する必要があります。

注意しください

  • リリースをビルドすると、デバッグコードが自動的に削除され、サービスが正常に実行されます。

  • 使ってます Debugger.Launch()デバッガー起動してアタッチするています。私がテストしているDebugger.Break()され、同様に仕事しませんでしたサービスの起動時に添付なしデバッガがまだ存在しないため(原因、「エラー1067:プロセスが予期せず終了します」)。

  • RequestAdditionalTimeサービスの起動により長いタイムアウトを設定します(コード自体を遅延させることはありませんが、すぐにDebugger.Launchステートメントを続行します)。そうしないと、サービスを開始するためのデフォルトのタイムアウトが短すぎbase.Onstart(args)て、デバッガーから十分に速く呼び出さないとサービスの開始が失敗します。実際には、10分のタイムアウトにより、デバッガーの起動直後に「サービスが応答しませんでした...」というメッセージが表示されなくなります。

  • 慣れれば、この方法は非常に簡単です。既存のサービスコードに4行追加するだけで、すぐに制御とデバッグを行うことができます。


1
好奇心から、Debugger.Launch()ユーザープロンプトでのユーザー操作にタイムアウトがあるかどうかを知っていますか?
Shiv 2014年

1
説明したように、その時間内にbase.RequestAdditionalTime(600000)呼び出さbase.OnStart(args)れない場合、サービスコントロールはサービスを10分間終了しません)。それとは別に、しばらくして管理者の資格情報を入力しなかった場合もUACが中止されることを覚えています(正確には秒数はわかりませんが、1分以内に入力する必要があると思います。それ以外の場合はUACが中止されます) 、デバッグセッションを終了します。
マット

2
これがCustomCommandメッセージのデバッグに最適な方法であることがわかりました。+1。
ジャスティン

40

私が通常行うことは、サービスのロジックを別のクラスにカプセル化し、それを「ランナー」クラスから開始することです。このランナークラスは、実際のサービスまたは単なるコンソールアプリケーションにすることができます。したがって、ソリューションには(少なくとも)3つのプロジェクトがあります。

/ConsoleRunner
   /....
/ServiceRunner
   /....
/ApplicationLogic
   /....

1
私も以前はこのアプローチを使用していましたが、これと上記の答えを組み合わせると効果的だと思います。
RobS 2009

27

Fabio ScopelによるこのYouTubeビデオ、Windowsサービスを非常にうまくデバッグする方法を説明しています...実際の方法は、ビデオの4:45に始まります...

これがビデオで説明されているコードです... Program.csファイルに、Debugセクションの要素を追加してください...

namespace YourNamespace
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
#if DEBUG
            Service1 myService = new Service1();
            myService.OnDebug();
            System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new Service1()
            };
            ServiceBase.Run(ServicesToRun);
#endif

        }
    }
}

Service1.csファイルにOnDebug()メソッドを追加します...

    public Service1()
    {
        InitializeComponent();
    }

    public void OnDebug()
    {
        OnStart(null);
    }

    protected override void OnStart(string[] args)
    {
        // your code to do something
    }

    protected override void OnStop()
    {
    }

使い方

基本的には、保護されていて外部からアクセスできないため、public void OnDebug()を呼び出すを作成する必要がOnStart(string[] args)あります。void Main()プログラムがで追加される#ifと、プリプロセッサ#DEBUG

Visual StudioはDEBUG、プロジェクトがデバッグモードでコンパイルされるかどうかを定義します。これにより、条件がtrueの場合にデバッグセクション(下記)を実行できます

Service1 myService = new Service1();
myService.OnDebug();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);

そして、それはコンソールアプリケーションのように実行されます。問題がなければ、モードReleaseを変更でき、通常のelseセクションがロジックをトリガーします


私はこの答えを探していました、なぜそれがそれほど低くランク付けされたのか分からない。他の人を助けるためにコードを説明した、またはおそらくより多くのコメント;)
Vinod Srivastav

14

更新

このアプローチは、はるかに簡単です。

http://www.codeproject.com/KB/dotnet/DebugWinServices.aspx

元の答えは後世に残しておきます。


私のサービスには、タイマーがカプセル化されたクラスがある傾向があります。これは、サービスが実行する作業があるかどうかを定期的にチェックするためです。

クラスを新しくして、サービスの起動中にStartEventLoop()を呼び出します。(このクラスは、コンソールアプリからも簡単に使用できます。)

この設計の良い副作用は、タイマーを設定する引数を使用して、サービスが実際に動作する前に遅延を設定できるため、デバッガーを手動で接続する時間があることです。

ps デバッガーを実行中のプロセスに手動で接続する方法...?

using System;
using System.Threading;
using System.Configuration;    

public class ServiceEventHandler
{
    Timer _timer;
    public ServiceEventHandler()
    {
        // get configuration etc.
        _timer = new Timer(
            new TimerCallback(EventTimerCallback)
            , null
            , Timeout.Infinite
            , Timeout.Infinite);
    }

    private void EventTimerCallback(object state)
    {
        // do something
    }

    public void StartEventLoop()
    {
        // wait a minute, then run every 30 minutes
        _timer.Change(TimeSpan.Parse("00:01:00"), TimeSpan.Parse("00:30:00");
    }
}

また、私は次のことも行っていました(以前の回答で既に言及されていますが、リリースビルドでの起動を回避するために条件付きコンパイラ[#if]フラグを使用しています)。

リリースでビルドするのを忘れて、クライアントデモで実行されているアプリでデバッガーが中断することがあるので、この方法でこれをやめました(恥ずかしい!)。

#if DEBUG
if (!System.Diagnostics.Debugger.IsAttached)
{
    System.Diagnostics.Debugger.Break();
}
#endif

// do something完了までに30分以上かかるとどうなりますか?
Vinod Srivastav 2018年

13

static void Main()
{
#if DEBUG
                // Run as interactive exe in debug mode to allow easy
                // debugging.

                var service = new MyService();
                service.OnStart(null);

                // Sleep the main thread indefinitely while the service code
                // runs in .OnStart

                Thread.Sleep(Timeout.Infinite);
#else
                // Run normally as service in release mode.

                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[]{ new MyService() };
                ServiceBase.Run(ServicesToRun);
#endif
}

[コードの説明がなく申し訳ありません-マークダウンの問題]デバッグビルドでは、MS Visual Studio(F5)から正常に実行されます。リリースビルドでは通常のサービスとして引き続き実行されます。
トーマスブラット

これを上記のクリスチャンKによるソリューションと組み合わせて "Environment.UserInteractive"プロパティを使用すると、ソリューションは非常にクリーンでシンプルです。
ベンロビンス

OnStartprotected、あなたはアクセスレベルを変更することはできません:(
エドゥアルト・ルカ

10

コマンドプロンプト(sc.exe)からサービスを開始することもできます。

個人的には、デバッグ段階でコードをスタンドアロンプ​​ログラムとして実行し、ほとんどのバグが解決されたら、サービスとして実行するように変更します。


10

以前は、プログラムをサービスまたは通常のアプリケーションとして起動するコマンドラインスイッチを使用していました。次に、IDEでスイッチを設定して、コードをステップ実行できるようにします。

一部の言語では、IDEで実行されているかどうかを実際に検出し、この切り替えを自動的に実行できます。

どの言語を使用していますか?


9

TopShelfライブラリを使用します。

コンソールアプリケーションを作成し、メインでセットアップを構成する

class Program
    {
        static void Main(string[] args)
        {
            HostFactory.Run(x =>
            {

                // setup service start and stop.
                x.Service<Controller>(s =>
                {
                    s.ConstructUsing(name => new Controller());
                    s.WhenStarted(controller => controller.Start());
                    s.WhenStopped(controller => controller.Stop());
                });

                // setup recovery here
                x.EnableServiceRecovery(rc =>
                {
                    rc.RestartService(delayInMinutes: 0);
                    rc.SetResetPeriod(days: 0);
                });

                x.RunAsLocalSystem();
            });
        }
}

public class Controller
    {
        public void Start()
        {

        }

        public void Stop()
        {

        }
    }

サービスをデバッグするには、Visual StudioでF5キーを押します。

サービスをインストールするには、cmd「console.exe install」と入力します

その後、Windowsサービスマネージャーでサービスを開始および停止できます。


彼らのライセンスは理解するのが
難し

彼らはApache License afaikを使用しています。Topshelfは、Windowsサービスの開発とデバッグに使用した最も簡単な方法です。とても使いやすい。コンソールアプリケーションとして開発します。1つのコマンドラインスイッチでサービスとしてインストールします。強くお勧めします。
2018年

トップシェルフは私に多くの時間を節約しました。Thx
L_7337

8

私はそれがあなたが使っているOSに依存すると思います、Vistaはセッション間の分離のためにサービスに接続するのがはるかに困難です。

過去に使用した2つのオプションは次のとおりです。

  • GFlags(Debugging Tools for Windows)を使用して、プロセスの永続的なデバッガーをセットアップします。これは「イメージファイル実行オプション」レジストリキーに存在し、非常に便利です。「デスクトップとの対話」を有効にするには、サービス設定を微調整する必要があると思います。これは、サービスだけでなく、すべてのタイプのデバッグに使用します。
  • もう1つのオプションは、コードを少し分離して、サービス部分を通常のアプリの起動と交換できるようにすることです。このように、単純なコマンドラインフラグを使用して、(サービスではなく)プロセスとして起動できるため、デバッグがはるかに簡単になります。

お役に立てれば。


GFlagsの場合は+1。これは、ソースコードを変更できない場合(またはソースコードがない場合)に特に役立ちます。
Chris Gillum、

6

OnStart()での初期化を含め、サービスのすべての側面をデバッグしながら、SCMのフレームワーク内で完全なサービス動作でサービスを実行できるようにしたい...「コンソール」モードまたは「アプリ」モードなし。

これを行うには、同じプロジェクトで、デバッグに使用する2番目のサービスを作成します。デバッグサービスは、通常どおり(つまり、サービスMMCプラグインで)起動すると、サービスホストプロセスを作成します。これにより、実際のサービスをまだ開始していない場合でも、デバッガーをアタッチするプロセスが提供されます。デバッガーをプロセスにアタッチした後、実際のサービスを開始すると、OnStart()を含め、サービスライフサイクルのどこにでも侵入できます。

最小限のコード侵入しか必要としないため、デバッグサービスはサービスセットアッププロジェクトに簡単に含めることができ、コードの1行をコメント化して1つのプロジェクトインストーラーを削除することで、製品リリースから簡単に削除できます。

詳細:

1)実装していると仮定してMyService、も作成しますMyServiceDebug。次のように両方にServiceBase配列に追加しProgram.csます:

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new MyService(),
            new MyServiceDebug()
        };
        ServiceBase.Run(ServicesToRun);
    }

2)実際のサービスとデバッグサービスをサービスプロジェクトのプロジェクトインストーラーに追加します。

ここに画像の説明を入力してください

サービスのセットアッププロジェクトにサービスプロジェクトの出力を追加すると、両方のサービス(実際のサービスとデバッグ)が含まれます。インストール後、両方のサービスがservice.msc MMCプラグインに表示されます。

3)MMCでデバッグサービスを開始します。

4)Visual Studioで、デバッグサービスによって開始されたプロセスにデバッガーをアタッチします。

5)実際のサービスを開始し、デバッグを楽しんでください。


5

サービスを作成するとき、すべてのサービスロジックをdllプロジェクトに入れ、このdllを呼び出す2つの「ホスト」を作成します。1つはWindowsサービスで、もう1つはコマンドラインアプリケーションです。

コマンドラインアプリケーションを使用してデバッグし、コマンドラインアプリケーションで再現できないバグに対してのみ、デバッガーを実際のサービスに接続します。

このアプローチを使用する場合、実際のサービスで実行中にすべてのコードをテストする必要があることを覚えておいてください。コマンドラインツールは優れたデバッグ支援ツールであり、環境が異なり、実際のサービスとまったく同じようには動作しません。


4

Windowsサービスを開発してデバッグするときは、通常、/ console起動パラメーターを追加してこれをチェックすることにより、コンソールアプリケーションとして実行します。生活をずっと楽にします。

static void Main(string[] args) {
    if (Console.In != StreamReader.Null) {
        if (args.Length > 0 && args[0] == "/console") {
            // Start your service work.
        }
    }
}

サービス固有の問題をデバッグする必要があるまで。
leppie 2008

確かに、実際のサービスプロセスにデバッガーをアタッチする必要があります。しかし、ほとんどの場合、バグはいずれかの方法で発生し、開発ははるかに容易になります。
モーリス


2

Windowsサービスをデバッグするために、GFlagsとregeditによって作成された.regファイルを組み合わせます。

  1. exe-nameとvsjitdebuggerを指定して、GFlagsを実行します。
  2. regeditを実行し、GFlagsがオプションを設定する場所に移動します。
  3. ファイルメニューから[キーのエクスポート]を選択します
  4. そのファイルを.reg拡張子でどこかに保存します
  5. サービスをデバッグしたいときはいつでも:.regファイルをダブルクリックします
  6. デバッグを停止する場合は、2番目の.regファイルをダブルクリックします。

または、次のスニペットを保存し、servicename.exeを目的の実行可能ファイル名に置き換えます。


debugon.reg:

Windowsレジストリエディターバージョン5.00

[HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Image File Execution Options \ servicename.exe]
"GlobalFlag" = "0x00000000"
"デバッガ" = "vsjitdebugger.exe"

debugoff.reg:

Windowsレジストリエディターバージョン5.00

[HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Image File Execution Options \ servicename.exe]
"GlobalFlag" = "0x00000000"

これはWin 7 / Win 2008でも動作しますか?それはsupport.microsoft.com/kb/824344からのアプローチですが、インタラクティブなサービスに依存しているため、殺されたと思いましたか?これは常に私の優先オプションでした(スタートアップの問題が本番環境で発生する可能性があるため、Debugger.Break()をコードに挿入することはオプションではない可能性があります)。
piers7

1

日常的な小規模なプログラミングでは、サービスを簡単にデバッグするために非常に簡単なトリックを実行しました。

サービスの開始時に、コマンドラインパラメータ「/ debug」を確認します。このパラメーターを使用してサービスが呼び出された場合、通常のサービスの起動は行わず、代わりにすべてのリスナーを起動し、「Debug in progress、press ok to end」というメッセージボックスを表示します。

したがって、私のサービスが通常の方法で開始されると、サービスとして開始されます。コマンドラインパラメータ/ debugで開始されると、通常のプログラムのように動作します。

VSでは、デバッグパラメータとして/ debugを追加し、サービスプログラムを直接開始します。

このようにして、ほとんどの小さな問題を簡単にデバッグできます。もちろん、一部のものはサービスとしてデバッグする必要がありますが、99%の場合はこれで十分です。



1

JOPの回答のバリエーションを使用します。コマンドラインパラメータを使用すると、プロジェクトのプロパティを使用して、またはWindowsサービスマネージャを介して、IDEでデバッグモードを設定できます。

protected override void OnStart(string[] args)
{
  if (args.Contains<string>("DEBUG_SERVICE"))
  {
    Debugger.Break();
  }
  ...
}


1

デバッガーランチをどこかに置いて、起動時にVisualstudioをアタッチするだけです

#if DEBUG
    Debugger.Launch();
#endif

また、管理者としてVSを起動する必要があります。また、別のユーザーがプロセスを自動的にデバッグできるようにする必要もあります(ここで説明します)。

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

1

WindowsサービステンプレートC#プロジェクトを使用して新しいサービスアプリを作成する ますhttps://github.com/HarpyWar/windows-service-template

コンソール/サービスモードが自動的に検出され、サービスの自動インストーラー/アンインストーラーがあり、最もよく使用される機能がいくつか含まれています。


1

追加の「デバッグ」メソッドなしで、統合されたVSユニットテストを使用して、サービスをテストするために使用した単純なメソッドを次に示します。

[TestMethod]
public void TestMyService()
{
    MyService fs = new MyService();

    var OnStart = fs.GetType().BaseType.GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

    OnStart.Invoke(fs, new object[] { null });
}

// As an extension method
public static void Start(this ServiceBase service, List<string> parameters)
{
     string[] par = parameters == null ? null : parameters.ToArray();

     var OnStart = service.GetType().GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

     OnStart.Invoke(service, new object[] { par });
}

1
static class Program
{
    static void Main()
    {
        #if DEBUG

        // TODO: Add code to start application here

        //    //If the mode is in debugging
        //    //create a new service instance
        Service1 myService = new Service1();

        //    //call the start method - this will start the Timer.
        myService.Start();

        //    //Set the Thread to sleep
        Thread.Sleep(300000);

        //    //Call the Stop method-this will stop the Timer.
        myService.Stop();

         #else
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new Service1() 
        };

        ServiceBase.Run(ServicesToRun);
         #endif
    }
}

これは簡単です。ソリューション構成設定をデバッグに変更し、プロジェクト/ソリューションを実行し、必要に応じてブレークポイントを追加するだけです。
バハムート

0

デバッグを行うには2つのオプションがあります。

  1. ログファイルを作成する:個人的には、アプリケーションログやイベントログを使用するのではなく、テキストファイルなどの別のログファイルを使用します。
  2. アプリケーションをコンソールアプリケーションに変換します。これにより、VSで使用できるすべてのデバッグツールが有効になります。

このトピックについて私が作成したこのブログ投稿を参照してください。


0

貼り付けるだけ

Debugger.Break();

コードのどこにでも。

例えば ​​、

internal static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        private static void Main()
        {
            Debugger.Break();
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new Service1()
            };
            ServiceBase.Run(ServicesToRun);
        }
    }

Debugger.Break();プログラムを実行するとヒットします。


0

最良のオプションは、 ' System.Diagnostics '名前空間を使用することです。

Visual Studioでデバッグモードとリリースモードを切り替えるには、以下のようにデバッグモードとリリースモードのif elseブロックでコードを囲みます。

#if DEBUG  // for debug mode
       **Debugger.Launch();**  //debugger will hit here
       foreach (var job in JobFactory.GetJobs())
            {
                //do something 
            }

#else    // for release mode
      **Debugger.Launch();**  //debugger will hit here
     // write code here to do something in Release mode.

#endif
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.