Has anyone ever tried to attach delphi to his own windows service(32 bit app.) process under Windows Server 2008 64 bit?
When I try to do this I get the error: Unable to create the process. The parameter is incorrect.
if anyone of you know how to do this, that help would be really appreciated.
Thanks!
Whilst you can debug a Delphi service there are a number of hoops that you need to jump through to make it work. I never bother and simply ensure that my services can run either as a service or as a standard app. When I want to debug I run as a standard app and so sidestep all the headaches.
I've hacked out all the code into a single file for the purpose of this answer, but you'd want to structure it a bit differently.
program MyService; uses SysUtils, Classes, Windows, Forms, SvcMgr; type TMyService = class(TService) private procedure ServiceStart(Sender: TService; var Started: Boolean); procedure ServiceStop(Sender: TService; var Stopped: Boolean); procedure ServicePause(Sender: TService; var Paused: Boolean); procedure ServiceExecute(Sender: TService); procedure ServiceContinue(Sender: TService; var Continued: Boolean); protected FDescription: string; FEventLogSourceName: string; procedure Initialise; virtual; abstract; class function CreateRunner: TObject; virtual; abstract; public constructor Create(AOwner: TComponent); override; function GetServiceController: TServiceController; override; end; TMyServiceClass = class of TMyService; { TMyService } constructor TMyService.Create(AOwner: TComponent); begin inherited; Initialise; OnStart := ServiceStart; OnStop := ServiceStop; OnPause := ServicePause; OnExecute := ServiceExecute; OnContinue := ServiceContinue; end; procedure TMyService.ServiceStart(Sender: TService; var Started: Boolean); begin Started := True; end; procedure TMyService.ServiceStop(Sender: TService; var Stopped: Boolean); begin Stopped := True; end; procedure TMyService.ServiceContinue(Sender: TService; var Continued: Boolean); begin ServiceStart(Sender, Continued); end; procedure TMyService.ServicePause(Sender: TService; var Paused: Boolean); begin ServiceStop(Sender, Paused); end; procedure TMyService.ServiceExecute(Sender: TService); var Runner: TObject; begin Runner := CreateRunner; Try while not Terminated do begin ServiceThread.ProcessRequests(True); end; Finally FreeAndNil(Runner); End; end; var Service: TMyService; procedure ServiceController(CtrlCode: DWORD); stdcall; begin Service.Controller(CtrlCode); end; function TMyService.GetServiceController: TServiceController; begin Result := ServiceController; end; procedure RunAsService(ServiceClass: TMyServiceClass; var Service); var Application: TServiceApplication; begin Application := SvcMgr.Application; Application.Initialize; Application.CreateForm(ServiceClass, Service); Application.Run; end; procedure RunAsStandardExecutable(ServiceClass: TMyServiceClass); var Application: TApplication; Runner: TObject; begin Application := Forms.Application; Application.Initialize; Runner := ServiceClass.CreateRunner; Try while True do begin Try Application.HandleMessage; Except Application.HandleException(Application); End; end; Finally FreeAndNil(Runner); End; end; procedure ServiceMain(ServiceClass: TMyServiceClass); begin if FindCmdLineSwitch('RunAsApp', ['-', '/'], True) then begin RunAsStandardExecutable(ServiceClass); end else begin RunAsService(ServiceClass, Service); end; end; begin ServiceMain(TMyService); end.
To use this you need to create a new class, inherited from TMyService
, and implement Initialise
and CreateRunner
. CreateRunner
is the key. In my services this creates an object which in turn opens a listening socket ready for clients to communicate over.
The standard app code is pretty basic. It doesn't even have a mechanism to terminate―it runs inside a while True
loop. That doesn't matter for my debugging needs.
Did you try running the IDE as Administrator?
I've already done such process attach under Win64, but I had to run the IDE with Administrator rights, as far as I remember.