Comment déboguer un service windows avec Delphi?
Est-il possible de déboguer complètement un service windows avec Delphi?
6 réponses
vous pouvez utiliser unitDebugService.pas de Colin Wilson NT Faible Niveau Utilitaires (page est allé, disponible dans la machine wayback)
et puis dans le 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.
de cette façon, vous pouvez exécuter à partir de Delphi avec le débogage (en définissant les paramètres du Débogueur de projet), utiliser L'EXE comme un service, ou exécuter à partir de la ligne de commande avec le -DEBUG
switch, et .
Il est en fait assez facile. Il suffit d'utiliser la directive DEBUG compilateur standard pour démarrer le service en tant qu'application console au lieu d'un service.
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.
utilisez Run - > attachez au processus. Vous pouvez ainsi déboguer un service sans modifier son code. La seule partie délicate est peut-être le débogage du code de démarrage du service, car la fixation peut prendre un certain temps, et le démarrage doit se faire dans les 30s (bien que vous puissiez modifier les fenêtres pour permettre un délai plus long). Vous pouvez utiliser un délai (sommeil...) pour vous permettre de fixer dans le temps, ou si vous avez juste besoin de voir ce qui se passe, vous pouvez utiliser OutputDebugString() pour imprimer à la sortie de débogage (utilisez la vue D'événement Delphi pour voir il.)
Oui, il y a: services de débogage: un moyen facile
créez-vous des services avec Delphi? Alors peut-être que vous êtes aussi ennuyé par le temps moyen de commencer, redémarrage, mise à mort et fixation le processus de service de l'application à chaque temps. Eh bien, il existe un recours.
Vous n'avez pas besoin de le faire. Au lieu d'exécuter Delphi en tant qu'application système et do quelques petites adaptations au service code.
j'ai essayé cela, mais apparaît seulement la fenêtre cpu avec les codes d'assemblage.
alors vous devez seulement résoudre ce problème.
fondamentalement, pour déboguer un service Win2, il y a plusieurs façons:
- utilisez la commande "Attach to process" pour attacher le débogueur au service déjà en cours d'exécution. Vous pouvez insérer des délais de démarrage pour avoir le temps d'attacher le débogueur, si vous avez besoin d'attacher au tout début. Cependant, vous devez également modifier le système pour augmenter les délais de service.
- Utiliser "options D'exécution de fichier Image" clé de registre à force de courir Delphi débogueur au démarrage du service. Les mêmes considérations sur les temps morts du système s'appliquent.
- convertissez le service temporaire en application habituelle et lancez-le sous débogueur normalement. Vous pouvez relancer IDE sous un compte utilisateur différent pour obtenir plus de privilèges pour le "service".
si, pour une raison quelconque, vous n'avez qu'une vue CPU de votre service après avoir commencé le débogage - cela signifie que le débogueur de Delphi ne peut pas trouver les informations de débogage pour votre service. C'est un problème différent et vous devriez chercher une solution.
Habituellement, vous devez faire:
- assurez-vous que le dossier de sortie de votre application de service est défini au dossier à partir duquel il sera chargé par le système. C'est-à-dire: si votre service est situé dans C:\Windows\System32 -ensuite, définissez le dossier de sortie à C:\Windows\System32. Ne copiez pas .fichier exe ailleurs à partir de votre dossier de sortie. Pour 64 systèmes, vous pouvez essayer alias (sysnative / SysWOW64) ou real name. Je pense qu'il est préférable de définir le chemin de sortie vers le dossier du projet et le service de réenregistrement pour être chargé à partir du dossier du projet.
- (optionnel) définir le chemin de sortie pour DCU dans le même dossier que .EXE.
- supprimez tous vos fichiers DCU.
- assurez-vous d'activer les options de débogage sur la page "Compiler" dans les options de projet.
- (optionnel) de plus, vous pouvez également inclure Options TD32/RSM / MAP sur la page "Linker".
- assurez-vous qu'il n'y a pas D'expert/extension IDE, qui peut modifier .fichier exe, informations de débogage ou date de modification du fichier pour ces fichiers.
- assurez-vous qu'il n'y a pas de vieux fichiers (DCU/exe) ailleurs.
- faire une reconstruction complète (projet/construire tout).
- exécutez votre service.
Oui, il est.
dans votre RMR:
Application.CreateForm(TMyService, MyService);
_ServiceInDebugMode := SysUtils.FindCmdLineSwitch('DEBUG', True);
if _ServiceInDebugMode then
DebugService(MyService)
else
SvcMgr.Application.Run;
DebugService est une procédure qui crée une forme de debug, un thread de contrôle de service et qui déclenche tout en appelant des formulaires.Application.Exécuter.
Vous pouvez comparer le thread de contrôle de service avec le SCM de Windows( Service Control Manager), le formulaire de débogage avec une application qui parle au SCM (comme les services.msc) pour lancer et arrêter les services. Le service doit également avoir son propre fil conducteur (service thread) pour répondre aux codes de contrôle provenant du SCM ou de notre thread de contrôle de service et un ou plusieurs threads séparés pour faire son travail réel. Vous voulez des threads séparés pour le travail réel (au lieu de le coder dans les handlers d'événement de votre descendant TService) pour s'assurer que le thread dans lequel le TService lui-même tourne est toujours libre de répondre aux codes de contrôle de la SCM et vous pouvez toujours arrêter et démarrer le service même si par hasard a/le worker thread est congeler.
cette approche vous permet de déboguer le code de l'application de service aussi bien, mais implique une bonne quantité de code et placer un couple de crochets dans les fonctions d'api de windows pour fonctionner correctement. Trop de choses à montrer ici, à court préavis. J'écrirai peut-être ça dans un article un jour.
En attendant, si vous ne voulez pas de code vous-même, vous avez deux options. Soit aller avec une bibliothèque comme SVCOM ou celle mentionnée par Mick qui faisons tout pour vous, ou en mode débogage by-pass le code de service tous ensemble et" simplement "démarrer votre service comme une" normale " demande de formulaires. Vous devrez démêler la fonctionnalité réelle de votre service des gestionnaires de code/événement de votre descendant TService, mais c'est quelque chose que je recommande de toute façon pour les raisons mentionnées ci-dessus.