Title: Comunicating two win services
Question: How I can comunicate two Windows Services when they are logged with a different user than Local System?
Answer:
To comunicate two windows services logged with a different user than local system, you must include in the project a .pas file with the following code:
(* ********************************************************* *)
(* ********************************************************* *)
unit mydsktop;
interface
function InitMyDesktop: boolean;
procedure DoneMyDeskTop;
implementation
uses Windows, SysUtils;
const
DefaultWinStation = 'WinSta0';
DefaultDesktop = 'Default';
var
hWinStaSave: HWINSTA;
hDskSave: HDESK;
hWinStaUs: HWINSTA;
hDskUs: HDESK;
(* ********************************************************* *)
(* ********************************************************* *)
function InitMyDesktop: boolean;
var
dwThrId: DWORD;
begin
dwThrId := GetCurrentThreadID();
hWinStaSave := GetProcessWindowStation();
hDskSave := GetThreadDesktop( dwThreadId );
hWinStaUs := OpenWindowStation( DefaultWindowStation, FALSE,
MAXIMUM_ALLOWED );
if ( hWinStaUs = 0 ) then
begin
OutputDebugString( PChar( SysErrorMessage( GetLastError )));
Result := false;
exit;
end;
if ( not SetProcessWindowStation( hWinStaUs ) ) then
begin
OutputDebugString( 'SetProcessWindowStation failed' );
Result := false;
exit;
end;
hDskUs := OpenDesktop( DefaultDesktop, 0, FALSE, MAXIMUM_ALLOWED );
if ( hDskUs = 0 ) then
begin
OutputDebugString( 'OpenDesktop failed' );
SetProcessWindowStation( hWinStaSave );
CloseWindowStation( hWinStaUs );
Result := false;
exit;
end;
Result := SetThreadDesktop( hDskUs );
if ( not Result ) then
OutputDebugString( PChar( SysErrorMessage( GetLastError )));
end;
(* ********************************************************* *)
(* ********************************************************* *)
procedure DoneMyDeskTop;
begin
SetThreadDesktop( hDskSave );
SetProcessWindowStation( hWinStaSave );
if ( hWinStaUs 0 ) then
CloseWindowStation( hWinStaUs );
if ( hDskUs 0 ) then
CloseDesktop( hDskUs );
end;
(* ********************************************************* *)
(* ********************************************************* *)
initialization
InitMyDesktop();
finalization
DoneMyDesktop();
end.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
NOTE: This file (mydsktop.pas) must be the first file in the uses session (in the project *.dpr file) to work as we need.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
To send broadcast messages between services you must register the aplications (both services) with the function
RegisterWindowMessage()
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
(* ********************************************************* *)
(* Service 1 *)
(* ********************************************************* *)
procedure TfrmMain.InitService;
var
wParam, lParam: integer;
FMsgsID: DWORD;
begin
FMsgsID := RegisterWindowMessage( 'Service1' );
// To Register my Service1
wParam := 1000;
lParam := 2000;
SendMessage( HWND_BROADCAST, FMsgsID, wParam, lParam );
// To Send a message to Service2
wParam := 0;
lParam := 1;
SendMessage( HWND_BROADCAST, FMsgsID, wParam, lParam );
end;
(* ********************************************************* *)
(* To get broadcast messages you must override the *)
(* DefaultHandler function. *)
(* ********************************************************* *)
procedure TfrmMain.DefaultHandler( var Message )
begin
with TMessage( Message ) do
begin
// Service1 Register
if ( ( wParam = 1000 ) and ( lParam = 2000 ) ) then
Service1ID := Msg
// Message from Service2
else if ( Msg = Service1ID ) then
// Your code here ...
end;
end;
(* ********************************************************* *)
(* Service 2 *)
(* ********************************************************* *)
procedure TfrmMain.InitService;
var
wParam, lParam: integer;
FMsgsID: DWORD;
begin
FMsgsID := RegisterWindowMessage( 'Service2' );
// To Register my Service2
wParam := 2000;
lParam := 1000;
SendMessage( HWND_BROADCAST, FMsgsID, wParam, lParam );
// To Send a message to Service1
wParam := 0;
lParam := 1;
SendMessage( HWND_BROADCAST, FMsgsID, wParam, lParam );
end;
(* ********************************************************* *)
(* To get broadcast messages you must override the *)
(* DefaultHandler function. *)
(* ********************************************************* *)
procedure TfrmMain.DefaultHandler( var Message )
begin
with TMessage( Message ) do
begin
// Service2 Register
if ( ( wParam = 2000 ) and ( lParam = 1000 ) ) then
Service2ID := Msg
// Message from Service1
else if ( Msg = Service2ID ) then
// Your code here ...
end;
end;