DelphiでWindowsサービスを完全にデバッグする方法はありますか?
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
スイッチを使用して実行したりできます。
実はとても簡単です。標準の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.
[実行]-> [プロセスにアタッチ]を使用します。このようにして、コードを変更せずにサービスをデバッグできます。唯一のトリッキーな部分は、サービス開始コードのデバッグです。これは、アタッチに時間がかかる場合があり、開始は30秒以内に行われる必要があるためです(ただし、Windowsを微調整してより長い時間を許可することもできます)。遅延(スリープ...)を使用して時間内にアタッチできるようにするか、何が起こるかを確認する必要がある場合は、OutputDebugString()を使用してデバッグ出力に出力できます(Delphiイベントビューを使用して確認します)。
はい、あります: デバッグサービス:簡単な方法
Delphiでサービスを作成していますか?次に、サービスプロセスアプリケーションを毎回起動、再起動、強制終了、および接続するという時間のかかる方法にも悩まされるかもしれません。さて、救済策があります。
これを行う必要はありません。代わりに、DelphiをSYSTEMアプリケーションとして実行し、サービスコードに若干の変更を加えます。
これを試しましたが、アセンブリコードを含むCPUウィンドウしか表示されません。
次に、この問題を解決するだけです。
基本的に、Win2サービスをデバッグするには、いくつかの方法があります。
何らかの理由でデバッグ開始後にサービスのCPUビューしかない場合、これはDelphiのデバッガーがサービスのデバッグ情報を見つけることができないことを意味します。これは別の問題であり、解決策を探す必要があります。
通常、次のことを行う必要があります。
はいあります。
あなたの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の子孫のコード/イベントハンドラーからサービスの実際の機能を解きほぐす必要がありますが、それは上記の理由からとにかくお勧めします。