To the main page...The list of my products...Some texts...Sample applications, tips, tricks...If you need support...
 

 
Self-starting configurable service
Step 4. How to receive windows message

A communication with service application is more complicated then with regular one. The thing is that the service usually has no access to the interactive desktop. Due to this reason all service windows live in another desktop and Windows do not support message sending between desktops. So it is not possible to send the message to the window in a service even service has such window.

Another way exists. The message can be send to the service thread. Several conditions should be met to do it:

  • service should process the message loop;
  • sender should know the ID of the service thread.

As you know the standard message handling code has a form

TMyHandler = class(...)
    procedure WMSomething(var Msg: TMessage); message WM_SOMETHING;

This code needs one more condition:

  • service should process the message loop correctly!

No jokes, native TService does not! SvCom does :)

Well, let's add this functionality to our example. The first thing to be done is to save somewhere the thread ID when the service starts and to delete this info at the service stop. Ini file is used for this purpose again. The thread ID is stored in the OnStart handler...





 
 
 
 
 

procedure TsvcServiceBase.svcServiceBaseStart(Sender: TNtService;
  var DoAction: Boolean);
var Ini: TIniFile;
begin
    Ini:=TIniFile.Create(ChangeFileExt(ParamStr(0), '.DAT'));
    Ini.WriteInteger(Name,'ThreadId',GetCurrentThreadId);
    Ini.Free;
end;

... and deleted in the OnStop event:





 
 
 
 
 

procedure TsvcServiceBase.svcServiceBaseStop(Sender: TNtService;
  var DoAction: Boolean);
var Ini: TIniFile;
begin
    Ini:=TIniFile.Create(ChangeFileExt(ParamStr(0), '.DAT'));
    Ini.WriteInteger(Name,'ThreadId',0);
    Ini.Free;
end;

Now client application is able to read the thread ID from the file and send the message to the service thread. Let's write the handle for sample message:

























 
 
 

const WM_BEEP = WM_USER+1;

type
  TsvcServiceBase = class(TNTService)
    procedure svcServiceBaseStart(Sender: TNtService;
      var DoAction: Boolean);
    procedure svcServiceBaseStop(Sender: TNtService;
      var DoAction: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure WMBeep(var Message: TMessage); message WM_BEEP;
  end;
  
var
  svcServiceBase: TsvcServiceBase;
  
implementation

{$R *.DFM}

procedure TsvcServiceBase.WMBeep(var Message: TMessage);
begin
    Windows.Beep(Message.WParam,Message.LParam);
end;

As you see we not only receive the message but we use its parameters to produce a sound of given length frequency. The client application that sends messages will be created on the next step.

The source code of this step is available here (zip, 3.3kb).

<< | Index | Step 1 | Step 2 | Step 3 | Step 4 | Step 5 | >>
Add your comment | Read comments


 
© 1998-2001 Alexey Dynnikov
My ICQ # is 18267212