Click here to Skip to main content
Click here to Skip to main content

Sending a message to the Main Frame Window of Another Application, given only the Process Handle

By , 8 Dec 1999
 

In order to send a message to another process, it is necessary to know the handle of the receiving window. However, if that process is created using CreateProcess or opened using OpenProcess, only the handles of the process and of it's main thread are known.

It is normally possible to find the window, if the title is known, simply by enumerating all windows and searching for the right window. When the name is unknown however, it is a little more complex to get its handle.

In order to find that handle it is, however, possible to scan all top-level windows and compare each window process Id with the Id received from the CreateProcess or the OpenProcess function. Please take note that not all Windows messages can be sent between processes. It is why use WM_COPYDATA is recommended.

Finally, remember that the message will need to be sent to the Main Frame. If it is intended for a child window ( a CView-derived class, for example ), it should be sent to the Main Frame, and then redirected in the target application.

In a private communication with a Senior Support Engineer at Microsoft, it has been noted that there is no guarantee that a process has any windows at all. It is also possible that a process has more than one window. Even if you get the correct window, it must know about and be able to handle the message being sent. A window always has a process, but a process can have zero to any number of windows, so there is no way to make a correlation between a process and a particular window.

I personally recommand a lot of care when using this method. However, this technique is working well in my projects, and I now use it for all inter-process communication. Furthermore, since I have included my code in several different projects, I have found only two problems with this code:

  1. The Process must have finished it's initialization. This can be verified with the following call made before the call to SendMessage :
    WaitForInputIdle( ProcessInfo.hProcess, INFINITE );
  2. The Process must be receiving its messages. In order to go around this problem, I place my calls to SendMessageToProcess in a while loop, which waits to the receiving application to send back a WM_COPYDATA message confirming reception.

To add a function that send a message to a Process, perfoms the steps listed bellow. NOTE: These steps assume that the name of the CWinApp-derived object is CMyWinApp.

  1. Add the Following members to the declaration of CMyWinApp in MYWINAPP.H:
    public:
    	void SendMessageToProcess(LPPROCESS_INFORMATION lpProcessInformation, 
    	                          UINT Msg, WPARAM wParam, LPARAM lParam);
    protected:
    	static BOOL CALLBACK EnumWindowCallBack(HWND hwnd, LPARAM lParam);
    
  2. Define the CMyWinApp::SendMessageToProcess function.
                         
    void CMyWinApp:: SendMessageToProcess(LPPROCESS_INFORMATION lpProcessInformation, 
                                          UINT Msg, WPARAM wParam, LPARAM lParam)
    {
    	FINDWINDOWHANDLESTRUCT fwhs;
    	fwhs.ProcessInfo = lpProcessInformation;
    	fwhs.hWndFound  = NULL;
    
    	EnumWindows ( EnumWindowCallBack, (LPARAM)&fwhs ) ;
    
    	SendMessage ( fwhs.hWndFound, Msg, wParam, lParam );
    }
    
  3. Define the CMyWinApp::EnumWindowCallBack function.
    BOOL CALLBACK CMyWinApp::EnumWindowCallBack(HWND hwnd, LPARAM lParam) 
    { 
    	FINDWINDOWHANDLESTRUCT * pfwhs = (FINDWINDOWHANDLESTRUCT * )lParam; 
    	DWORD ProcessId; 
    	CString Title; 
    	GetWindowThreadProcessId ( hwnd, &ProcessId ); 
    
    	// note: In order to make sure we have the MainFrame, verify that the title 
    	// has Zero-Length. Under Windows 98, sometimes the Client Window ( which doesn't 
    	// have a title ) is enumerated before the MainFrame 
    
    	CWnd::FromHandle( hwnd )->GetWindowText(Title);
    	if ( ProcessId  == pfwhs->ProcessInfo->dwProcessId && Title.GetLength() != 0) 
    	{ 
    		pfwhs->hWndFound = hwnd; 
    		return false; 
    	} 
    	else 
    	{ 
    		// Keep enumerating 
    		return true; 
    	} 
    }
    

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Martin-Pierre Frenette
Web Developer
Canada Canada
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 1memberRavindran Shanmugam12 Jul '10 - 8:36 
didnt get the proper information
Generalmight help: similar business solutiongroupSymfund10 Oct '09 - 14:34 
http://www.autoitscript.com/autoit3/docs/tutorials/notepad/notepad.htm[^]
Questionblock messages from other applications ?? [modified]memberkob-kob24 May '09 - 6:06 
How can i block messages from other applications to my application. ??
( i would like to know which application have sent the message )
Thanks.
 
modified on Monday, May 25, 2009 3:49 AM

QuestionHow HWND_BROADCAST Works?memberEsonix22 Feb '07 - 0:56 
Hi
Can u tell me how HWND_BROADCAST works?I want to pass information to all system processes that now i'm writing in standard ENGLIST(U.S) language.It possible then help me.
 
Md. Mostafijur Rahman

GeneralFacing problem while getting Handle of an ApplicationmemberRaj241128 Mar '06 - 23:06 
Hi,
 
I am facing problem while retreiving the handle of the MSPAINT window which is opened by our application using CreateProcess. Inside SendMessageToProcess() function, EnumWindows() function is called.
 
SendMessageToProcess(LPPROCESS_INFORMATION lpProcessInformation, UINT Msg, WPARAM wParam, LPARAM lParam)
{
FINDWINDOWHANDLESTRUCT fwhs;
fwhs.ProcessInfo = lpProcessInformation;
fwhs.hWndFound = NULL;
 
EnumWindows ( EnumWindowCallBack, (LPARAM)&fwhs ) ;
.........
}
 
Inside EnumWindowCallBack() function, the process id is not matching with the process which we have created through CreateProcess function.
 
BOOL CALLBACK EnumWindowCallBack(HWND hwnd, LPARAM lParam)
{
FINDWINDOWHANDLESTRUCT * pfwhs = (FINDWINDOWHANDLESTRUCT * )lParam;
DWORD ProcessId;
GetWindowThreadProcessId ( hwnd, &ProcessId );
if ( ProcessId == pfwhs->ProcessInfo->dwProcessId )
{
pfwhs->hWndFound = hwnd;
return false;
}
else
{
// Keep enumerating
return true;
}
}
 
This code is not working correctly on Japanese OS. why is it happening so? Do i need to set some parameters while creating the process?
Please let me know at earliest.
GeneralRe: Facing problem while getting Handle of an Applicationmembertor sen3 Apr '06 - 22:30 
Hi,
 
I have the same problem.
EnumWindows function enumerates only few window handles. No one which I find.
 
I think this is privilege problem. (I run this from localsystem user context because NT service...)
 

OS:
XP PRO SP2 PL
 
If I find the solution I'll let you.
GeneralRe: Facing problem while getting Handle of an ApplicationmemberRaj24114 Apr '06 - 0:41 
Hi,
 
I got the solution. Give sleep of 2-3 secs between createprocess and sending the message.
 

GeneralThank youmembertsurutsuru18 Apr '05 - 6:14 
I've been looking for a way to do this all weekend. Thanks! Cool | :cool:
Questionhow to use itmemberroel the reds2 Nov '04 - 20:16 
would you please give me an example how to call this method, what should be the parameter?
 
SendMessageToProcess(LPPROCESS_INFORMATION lpProcessInformation,
UINT Msg, WPARAM wParam, LPARAM lParam)
GeneralGive me some example of inter process communication using call back functionmemberumer shabbir25 Aug '04 - 20:22 
Give me some example of inter process communication using call back function
 
Umer
GeneralSend message to another applicationmemberxenia2724 Dec '03 - 21:40 
Hi,
 
I have this problem...I know the handle of the destination application...and the handle is created by CreateProcess...
 
Now I try to use SendMessage with WM_COPYDATA and I got this error message (error code 183..which means ERROR_ALREADY_EXISTS) What should I do???
 

Xenia
GeneralSending Message to MessageBoxmemberAhmer Syed9 Dec '03 - 18:53 
Hello
My aim is to send a message of Yes to a messagebox of other application can u help me on it i will be really thankfull to u
 
Thanx
 
Ahmer Syed
QuestionHow to find window?memberdarwinw18 Nov '03 - 8:24 
if an app is minimized/hide or sits in system tray, can we still find a handle to that app? is FindWindow works if so?
AnswerRe: How to find window?membercrouchie199830 Apr '04 - 13:01 
Yep Poke tongue | ;-P
GeneralPassing instruction to the createprocess command promptmembervgandhi13 Aug '03 - 13:48 
Hi there,
I wanted to ask you if we use the createprocess command for some command line function and if that function requires a prompt for (y/n) confirmation how do we pass in yes or no to that command prompt window. for example the cacls function if i have something where my strcommand looks like
cacls temp \t \g user:W and i make a call to
CreateProcess(NULL, // command is part of input string
strcommand , // (writeable) command string
NULL, // process security
NULL, // thread security
TRUE, // inherit handles flag
0, // flags
NULL, // inherit environment
NULL, // inherit directory
&startup, // STARTUPINFO
&procinfo);
now if i want to type in Y at the confirmation window so that the user doesnt have a choice how do I do that. The application that I am running will call createprocess and give the user a chance to type Y Please let me know thanks
 
vg
Generalconfusedmemberratass200210 Feb '03 - 19:07 
who->ProcessInfo->dwProcessId=(DWORD)1626472448;
SendMessageToProcess(who->ProcessInfo ,LVM_GETITEMCOUNT,0,0);
 
I keep getting type errors.
what is the correct way to call SendMessageToProcess?
 
I just want to send a message to a ListView on another DialogBox. I can find the process id and window handle using Spy++ for now. Also if I want to send a message to a control of another app, can I directly talk to it using its handle?
 

Confused | :confused:
Generalgive me an examplememberratass200210 Feb '03 - 19:00 
How do I actually use this function?
Generalgetguithreadmessage()memberAnonymous8 Jul '02 - 11:21 
getguithreadmessage() fails why?
GeneralWindow event listenermemberAnonymous11 Jun '02 - 2:37 
Hi!
 
Would it be possible to listen to window events from another process?
 
For example, my application starts another application that displays
a simple form with a button. When the user presses that button, my
application should be notified about the BN_CLICKED(BUTTONID) event.
 
Thanks
 
/// M R
GeneralRe: Window event listenermemberSilent Mobius7 Jun '04 - 0:05 
You should hook the process (look at ::SetWindowsHookEx). Then you get every messages from the process, for what you are looking for. I hope it helps
Mobius
 
-----------------------------------------------------------
"Eritis sicut deus, scientes bonum et malum"
Faust
Questionhow to set window to foregroun in win2kmemberjodon24 Dec '01 - 18:19 
When I use SetForegroundWindow API, but this API didn't general true result.Confused | :confused:
QuestionHow to send VK_? message?memberXuqiang Bai16 Oct '01 - 15:06 
Hi,
 
I want to send VK_? message to another window(process), like "Alt + E" message.
So i do as
SendMessageToProcess(&processInfo, WM_COMMAND, VK_MENU, 0);
SendMessageToProcess(&processInfo, WM_COMMAND, 0x45, 0); //0x45 is VK_E
but it does not work.
Is something wrong with me?
 
Thanks for any advice.
 
Bai.
AnswerRe: How to send VK_? message?memberAnonymous17 Oct '01 - 8:39 
dafd
AnswerRe: How to send VK_? message?memberTim Smith17 Oct '01 - 9:15 
Take a look at the WM_CHAR and WM_KEYDOWN/WM_KEYUP messages.
 
Tim Smith
Descartes Systems Sciences, Inc.
AnswerRe: How to send VK_? message?memberNavin17 Oct '01 - 9:19 
The problem is that the VK_(whatever) are key codes, not Windows messages. So you have a few options, depending on what you want to do:
 
1. If, in this example, Alt-E might bring up a menu, you can send a WM_COMMAND message for that item:
SendMessage(hwnd, WM_COMMAND, IDR_SOME_MENU_ITEM, 0);
 
2. If you have the code for both processes, you can use custom-defined messages to communicate in this way.
 
3. Although I've never tried it, you can try sending a WM_CHAR, WM_KEYDOWN, and/or WM_KEYUP message.
 

 
The early bird may get the worm, but the second mouse gets the cheese.
GeneralIf you have the code of both projectsmemberMartin-Pierre Frenette17 Oct '01 - 9:25 
If you have the code of both projects, you should really use the : WM_COPYDATA message.
 
If I remember correctly ( and please bear in mind that I wrote this article a few years ago ), only the WM_COPYDATA message was really properly sent.
 
If someone tries it succesfully thought, I would like to hear about it !
QuestionFINDWINDOWHANDLESTRUCT ?memberLuc18 Jan '01 - 0:07 
Hi
 
can you tell me where I can find the FINDWINDOWHANDLESTRUCT
 
Tanx
AnswerRe: FINDWINDOWHANDLESTRUCT ?memberck7 May '01 - 1:14 
typedef struct _FINDWINDOWHANDLESTRUCT {
LPPROCESS_INFORMATION ProcessInfo;
HWND hWndFound;
} FINDWINDOWHANDLESTRUCT;
 
Blush | :O

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130516.1 | Last Updated 9 Dec 1999
Article Copyright 1999 by Martin-Pierre Frenette
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid