joshuayip
asked on
Send Message from TService to Standard Exe
Hi experts,
I have a Tservice which I would like to send notification of some information to a standard exe. e.g. connection active or not, date of the last update. I havent come to discover many options to do this. If yes, would like to hear from you.
I am thinking about using CreateFileMappnig and use the shared memory to pass data around. However I am stuck at section where the std exe was not able to retrive the map handle after the service has started first. If I start the std exe first, then start the service, the message seems to be sending correctly from the service to the std exe. But if I turn on the service first , then the std app, the message was not received by the std exe.
Joshua
edit: I am sorry guys, I should have posted this to the Delphi language section. I only realize this after I click submit. And I cant seems to find any link to change the channel to delphi
I have a Tservice which I would like to send notification of some information to a standard exe. e.g. connection active or not, date of the last update. I havent come to discover many options to do this. If yes, would like to hear from you.
I am thinking about using CreateFileMappnig and use the shared memory to pass data around. However I am stuck at section where the std exe was not able to retrive the map handle after the service has started first. If I start the std exe first, then start the service, the message seems to be sending correctly from the service to the std exe. But if I turn on the service first , then the std app, the message was not received by the std exe.
Joshua
edit: I am sorry guys, I should have posted this to the Delphi language section. I only realize this after I click submit. And I cant seems to find any link to change the channel to delphi
ASKER
Hi Cookre, thanks for your response.
That is what I did. I was able to send the message from the service through if I start the std exe first, then start the service. I notice that if I start the service first , my std exe was able to obtain the
In the std exe, at formcreate, I have
TheMsgVal := RegisterWindowMessage(TheM sgConstant );
TheMapHnd := ObtainMappingHandle;
Where ObtainMappingHandle is
function ObtainMappingHandle: THandle;
begin
Result := CreateFileMapping($FFFFFFF F,nil,PAGE _READWRITE ,0,MaxMapL en,TheMapp ingConstan t);
if Result <> 0 then
if GetLastError = ERROR_ALREADY_EXISTS then
begin
CloseHandle(Result);
Result := OpenFileMapping(FILE_MAP_W RITE,False ,TheMappin gConstant) ;
end;
end;
A sample code I have showed that I should override the WndProc.
procedure TForm1.WndProc(Var TheMsg: TMessage);
Var
ThePtr : PChar;
TmpBmp : TBitmap;
begin
if TheMsg.Msg = TheMsgVal then
case TheMsg.wParam of
wpString : if TheMapHnd <> 0 then
begin
ThePtr := MapViewOfFile(TheMapHnd,FI LE_MAP_WRI TE,0,0,0);
edtStringRec.Text := ThePtr;
UnmapViewOfFile(ThePtr);
end;
wpValue : edtValueRec.Text := IntToStr(TheMsg.lParam);
wpBitmap : begin
TmpBmp := TBitmap.Create;
try
TmpBmp.Handle := TheMsg.lParam;
Image2.Picture.Bitmap.Widt h := TmpBmp.Width;
Image2.Picture.Bitmap.Heig ht := TmpBmp.Height;
Image2.Picture.Bitmap.Canv as.Draw(0, 0,TmpBmp);
finally
TmpBmp.ReleaseHandle;
TmpBmp.Free;
end;
end;
wpShutDown : LookForApp(True);
end;
Inherited WndProc(TheMsg);
end;
So this actually works, when I start the std exe first, then the service. But it doesnt work the other way round. I notice if I start the service first, then the std exe, the TheMapHnd was showign 0 (on timer, obtainmappinghandle)
-----
On the service side, I also do the following
TheMsgVal := RegisterWindowMessage(TheM sgConstant );
TheMapHnd := ObtainMappingHandle;
On Timer ,
I do the following
if TheHWnd = 0 then
TheHWnd := FindWindow('TForm1','Test Application #1');
ThePtr := MapViewOfFile(TheMapHnd,FI LE_MAP_WRI TE,0,0,0);
StrPLCopy(ThePtr,IntToStr( DummyCount ),MaxMapLe n);
SendMessage(TheHWnd,TheMsg Val,wpStri ng,0);
UnmapViewOfFile(ThePtr);
Is there anything I am not doing correctly here? Thanks
Joshua
That is what I did. I was able to send the message from the service through if I start the std exe first, then start the service. I notice that if I start the service first , my std exe was able to obtain the
In the std exe, at formcreate, I have
TheMsgVal := RegisterWindowMessage(TheM
TheMapHnd := ObtainMappingHandle;
Where ObtainMappingHandle is
function ObtainMappingHandle: THandle;
begin
Result := CreateFileMapping($FFFFFFF
if Result <> 0 then
if GetLastError = ERROR_ALREADY_EXISTS then
begin
CloseHandle(Result);
Result := OpenFileMapping(FILE_MAP_W
end;
end;
A sample code I have showed that I should override the WndProc.
procedure TForm1.WndProc(Var TheMsg: TMessage);
Var
ThePtr : PChar;
TmpBmp : TBitmap;
begin
if TheMsg.Msg = TheMsgVal then
case TheMsg.wParam of
wpString : if TheMapHnd <> 0 then
begin
ThePtr := MapViewOfFile(TheMapHnd,FI
edtStringRec.Text := ThePtr;
UnmapViewOfFile(ThePtr);
end;
wpValue : edtValueRec.Text := IntToStr(TheMsg.lParam);
wpBitmap : begin
TmpBmp := TBitmap.Create;
try
TmpBmp.Handle := TheMsg.lParam;
Image2.Picture.Bitmap.Widt
Image2.Picture.Bitmap.Heig
Image2.Picture.Bitmap.Canv
finally
TmpBmp.ReleaseHandle;
TmpBmp.Free;
end;
end;
wpShutDown : LookForApp(True);
end;
Inherited WndProc(TheMsg);
end;
So this actually works, when I start the std exe first, then the service. But it doesnt work the other way round. I notice if I start the service first, then the std exe, the TheMapHnd was showign 0 (on timer, obtainmappinghandle)
-----
On the service side, I also do the following
TheMsgVal := RegisterWindowMessage(TheM
TheMapHnd := ObtainMappingHandle;
On Timer ,
I do the following
if TheHWnd = 0 then
TheHWnd := FindWindow('TForm1','Test Application #1');
ThePtr := MapViewOfFile(TheMapHnd,FI
StrPLCopy(ThePtr,IntToStr(
SendMessage(TheHWnd,TheMsg
UnmapViewOfFile(ThePtr);
Is there anything I am not doing correctly here? Thanks
Joshua
Your second parm to CreateFileMapping() is null, resulting in a default security descriptor. This means that only processes with rights equal to or higher than the creating process will have access to the map.
Presuming the service is started under the local system account, you'll have to specify user level security descriptor.
See CreateFileMapping():
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/createfilemapping.asp?frame=true
Presuming the service is started under the local system account, you'll have to specify user level security descriptor.
See CreateFileMapping():
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/createfilemapping.asp?frame=true
ASKER
Thanks Cookre again for the reply.
I am not familiar with user level security descriptor that you have mentioned. I have looked the documentation. All I know is I have to create an object of type PSecurityAttributes , which has 3 properties I am suppose to initialize. (nLength, lpSecurityDescriptor, and bInheritHandle).
An example of a security descriptor parameter for CreateFileMapping in delphi would be much appreciated. Thanks
Joshua
I am not familiar with user level security descriptor that you have mentioned. I have looked the documentation. All I know is I have to create an object of type PSecurityAttributes , which has 3 properties I am suppose to initialize. (nLength, lpSecurityDescriptor, and bInheritHandle).
An example of a security descriptor parameter for CreateFileMapping in delphi would be much appreciated. Thanks
Joshua
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks for your reply again. It is madness in there. I have no idea what it is talking about. But I found some articles related to creating mutex
http://www.jrsoftware.org/iskb.php?mutexsessions
I have absolutely no idea what are mutexes before you mentioned it.
From your last reply you mentioned I should be specifying NULL DACL, as oppose to null DACL. I am sorry but I dont get this.
I guess this kind of service is kind of complicated for a new bie in service to write. Thanks again for your guidance.
Joshua
http://www.jrsoftware.org/iskb.php?mutexsessions
I have absolutely no idea what are mutexes before you mentioned it.
From your last reply you mentioned I should be specifying NULL DACL, as oppose to null DACL. I am sorry but I dont get this.
I guess this kind of service is kind of complicated for a new bie in service to write. Thanks again for your guidance.
Joshua
If all you want to do is send notifications with no more than a DWORD, just use the windows message queue:
1) Create custom messageID with RegisterWindowMessage()
2) Send messages back and forth with PostMessage(), or, if you want synchrony, SendMessage().