web-dev-qa-db-ja.com

DelphiでWindowsサービスをデバッグする方法は?

DelphiでWindowsサービスを完全にデバッグする方法はありますか?

26
Daniel Grillo

UnitDebugService.pasはから使用できます Colin WilsonのNT低レベルユーティリティ (ページがなくなった、 ウェイバックマシンで利用可能

そしてDPRで:

begin
  if (paramCount > 0) and (SameText(ParamStr(1), '-DEBUG')) then
  begin
    FreeAndNil (Application);
    Application := TDebugServiceApplication.Create(nil);
  end;

  //... the rest of the normal DPR code
end.

このようにして、デバッグを使用してDelphi内から実行したり(プロジェクトのデバッガーパラメーターを設定したり)、EXEをサービスとして使用したり、コマンドラインから-DEBUGスイッチを使用して実行したりできます。

26
jasonpenny

実はとても簡単です。標準のDEBUGコンパイラ指令を使用して、サービスではなくコンソールアプリケーションとしてサービスを開始します。

program MyServiceApp;

{$ifdef DEBUG}
  {$APPTYPE CONSOLE}
{$endif}

uses
  System.SysUtils,

[..]

begin
  {$ifdef DEBUG}
  try
    // In debug mode the server acts as a console application.
    WriteLn('MyServiceApp DEBUG mode. Press enter to exit.');

    // Create the TService descendant manually.
    ServerContainer1 := TServerContainer.Create(nil);

    // Simulate service start.
    ServerContainer1.ServiceStart(ServerContainer1, MyDummyBoolean);

    // Keep the console box running (ServerContainer1 code runs in the background)
    ReadLn;

    // On exit, destroy the service object.
    FreeAndNil(ServerContainer1);
  except
    on E: Exception do
    begin
      Writeln(E.ClassName, ': ', E.Message);
      WriteLn('Press enter to exit.');
      ReadLn;
    end;
  end;
  {$else}
  // Run as a true windows service (release).
  if not Application.DelayInitialize or Application.Installing then
    Application.Initialize;
  Application.CreateForm(TServerContainer, ServerContainer1);
  Application.Run;
  {$endif}
end.
19
Scott Beltgens

[実行]-> [プロセスにアタッチ]を使用します。このようにして、コードを変更せずにサービスをデバッグできます。唯一のトリッキーな部分は、サービス開始コードのデバッグです。これは、アタッチに時間がかかる場合があり、開始は30秒以内に行われる必要があるためです(ただし、Windowsを微調整してより長い時間を許可することもできます)。遅延(スリープ...)を使用して時間内にアタッチできるようにするか、何が起こるかを確認する必要がある場合は、OutputDebugString()を使用してデバッグ出力に出力できます(Delphiイベントビューを使用して確認します)。

14
user160694

はい、あります: デバッグサービス:簡単な方法

Delphiでサービスを作成していますか?次に、サービスプロセスアプリケーションを毎回起動、再起動、強制終了、および接続するという時間のかかる方法にも悩まされるかもしれません。さて、救済策があります。

これを行う必要はありません。代わりに、DelphiをSYSTEMアプリケーションとして実行し、サービスコードに若干の変更を加えます。

6
Mick

これを試しましたが、アセンブリコードを含むCPUウィンドウしか表示されません。

次に、この問題を解決するだけです。

基本的に、Win2サービスをデバッグするには、いくつかの方法があります。

  • 「プロセスにアタッチ」コマンドを使用して、すでに実行中のサービスにデバッガーをアタッチします。最初にアタッチする必要がある場合は、デバッガーをアタッチする時間を確保するために、起動遅延を挿入できます。ただし、サービスタイムアウトを増やすには、システムを微調整する必要もあります。
  • "Image File Execution Options"レジストリキー を使用して、サービスの起動時にDelphiのデバッガを強制的に実行します。システムタイムアウトに関する同じ考慮事項が適用されます。
  • サービスを通常のアプリケーションに一時的に変換し、通常のデバッガーで実行します。別のユーザーアカウントでIDEを再起動して、「サービス」の権限を増やすことができます。

何らかの理由でデバッグ開始後にサービスのCPUビューしかない場合、これはDelphiのデバッガーがサービスのデバッグ情報を見つけることができないことを意味します。これは別の問題であり、解決策を探す必要があります。

通常、次のことを行う必要があります。

  1. サービスアプリケーションの出力フォルダーが、システムによってロードされるフォルダーに設定されていることを確認してください。つまりサービスがC:\ Windows\System32にある場合は、出力フォルダーをC:\ Windows\System32に設定します。 .exeファイルを出力フォルダーの他の場所にコピーしないでください。 64システムの場合、エイリアス(sysnative/SysWOW64)または本名を試すことができます。プロジェクトのフォルダへの出力パスを設定し、プロジェクトフォルダからロードするサービスを再登録するのが最善だと思います。
  2. (オプション)DCUの出力パスを.exeファイルと同じフォルダーに設定します。
  3. すべてのDCUファイルを削除します。
  4. プロジェクトオプションの「コンパイラ」ページでデバッグオプションを有効にしてください。
  5. (オプション)さらに、「リンカー」ページにTD32/RSM/MAPオプションを含めることもできます。
  6. これらのファイルの.exeファイル、デバッグ情報、またはファイル変更日を変更する可能性のあるIDEエキスパート/拡張子がないことを確認してください。
  7. 他の場所に古いファイル(DCU/exe)がないことを確認してください。
  8. 完全な再構築を行います(プロジェクト/すべて構築)。
  9. サービスを実行します。
5
Alex

はいあります。

あなたのdprで:

Application.CreateForm(TMyService, MyService);

_ServiceInDebugMode := SysUtils.FindCmdLineSwitch('DEBUG', True);
if _ServiceInDebugMode then
  DebugService(MyService)
else
  SvcMgr.Application.Run;

DebugServiceは、デバッグフォーム、サービス制御スレッドを作成し、Forms.Application.Runを呼び出してすべてを開始するプロシージャです。

サービス制御スレッドをWindowsのSCM(サービスコントロールマネージャー)と比較できます。デバッグフォームは、SCMと通信してサービスを開始および停止するアプリケーション(services.mscなど)と比較できます。また、サービスには、SCMまたはサービス制御スレッドからの制御コードに応答するための独自のスレッド(サービススレッド)と、実際の作業を行うための1つ以上の個別のスレッドが必要です。 TService自体が実行されるスレッドが常にSCMからの制御コードに自由に応答できるようにするために、実際の作業用に(TServiceの子孫のイベントハンドラーでコーディングするのではなく)個別のスレッドが必要です。偶然に/ワーカースレッドがフリーズした場合でもサービスを開始します。

このアプローチでは、サービスアプリのコードもデバッグできますが、適切に機能させるには、かなりの量のコードと、WindowsAPI関数にいくつかのフックを配置する必要があります。急いでここに表示するには多すぎます。多分いつか記事に書いてみます。

それまでの間、すべてを自分でコーディングしたくない場合は、2つのオプションがあります。 SVCOMなどのライブラリまたはMickが言及したライブラリを使用してすべてを実行するか、デバッグモードのときに、サービスコードをすべてバイパスして、「通常の」フォームアプリケーションとしてサービスを「単純に」開始します。 TServiceの子孫のコード/イベントハンドラーからサービスの実際の機能を解きほぐす必要がありますが、それは上記の理由からとにかくお勧めします。

3
Marjan Venema