One of the most popular way of Inter-Process Communication is over Windows Messages using SendMessage and PostMessage functions.
In this case one process creates new (very often invisible) window and “listen” for specific window messages. Second process needs to know window handle of the first process – usually can get it over command line parameter or to use FindWindow function to find the window with specific title or created with specific Class name. The process that listen to the messages we are going to call Server, and the one that will send the messages we could call Client.
Server side
Creating new invisible window is not a big deal:
WNDCLASS wc; ZeroMemory(&wc, sizeof(wc)); wc.lpfnWndProc = WndProc; wc.hInstance = ::GetModuleHandle(NULL); wc.lpszClassName = L"www.cpp-blog.com"; // first we need to register our window class // - the most impotent member is a pointer to WndProc function if (!::RegisterClass(&wc)) { wprintf(L"RegisterClass failed!\n"); return 1; } HWND hWnd = ::CreateWindow(L"www.cpp-blog.com", L"www.cpp-blog.com", 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); // here comes Message loop ...
… and our WndProc …
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; }
If you have a trouble with Creating window and WndProc, check very good article about that here.
We should define our own message:
#define WM_CPPBLOGMSG (WM_APP+0x001)…and extend WinProc method:
case WM_CPPBLOGMSG: wprintf(L"Message received wParam=%d, lParam=%d\n", wParam, lParam); break;
Client Side
Client side is even easier, just find handle and use SendMessage or PostMessage. Here is complete code of the one simple message:
#define WM_CPPBLOGMSG (WM_APP+0x001) int _tmain(int argc, _TCHAR* argv[]) { HWND hServerWnd = ::FindWindow(L"www.cpp-blog.com", NULL); if (NULL == hServerWnd) { wprintf(L"Can't find Server window!\n"); return 1; } ::PostMessage(hServerWnd, WM_CPPBLOGMSG, 123, 456); return 0; }
It’s very simple … isn’t ?
Windows Vista & Windows 7
Under Windows Vista this wil not work in case that Server and Client are not running as the same user and with the same privileges (e.g. Server is Elevated). But in our scenario when we start second process to do some admin tasks for you, that second process will be Elevated and PostMessage will fail. Why? Security – you can NOT Send or Post message to higher privilege application windows.
Solution is to change Window Message Filter using ChangeWindowMessageFilter or ChangeWindowMessageFilterEx function.
simple call that method on the Server side:
ChangeWindowMessageFilter(WM_CPPBLOGMSG, MSGFLT_ADD);
… will allow you to send message from Client to the Server process. Anyway, if you need to make runnable code on Windows XP/2000 too, you will have to use GetProcAddress for importing those functions instead of direct call, because function is available only under Windows Vista and higher.
Conclusion
Inter-Process communication over Windows Messages is probably the most simplest way, very easy to use, you can integrate without any problem in your existing window and use it with few extra lines of code. Under Vista or higher you have to set additional filter, but that is also not so difficult. Also bi-directional support could be made making client to act as a server too.
Pros
- easy to use
- easy to integrate in existing code
- very good documented
- many examples
- could be used from almost every language or even script languages
Cons
- low security – everyone could simulate or hook messages
- it is possible to transfer only lParam/wParam but no binary data or strings*
- no real bi-directional support
*For transfere binary data or strings you can use WM_COPYDATA message read more here
In next post, I’m going to describe how to use Shared Memory to exchange data between two processes.
See you soon.

No Comments » 