简体   繁体   中英

How can I get a message from another process when I don't have a window handle?

I have 2 programs, and I need a way for one of them to somehow send a message to the other. I've looked into the SendMessage function in the Win32 API, and while it works great as long as you have a window handle, my program needs to be able to run while logged off under a service, which means it cannot create a window handle.

Is there any way I can receive messages from another process without having a window handle created? I've been looking to see if Win32 has some other way that I can hook into the messaging so that I don't depend on having a window handle, but there has to be some way to communicate between processes at a basic level, doesn't there?

I have looked into using Pipe's to do this, but have run into huge permissions issues with that on top of that being much higher level than I'm really looking for. All I need to be able to do is send a simple custom int message so my process knows it's time to shut down.

If it's really as simple as signalling the other program to shut down, then you can create a named event . Both processes create the event with the same name. One watches it and the other can signal it. The one watching can do that with a modified message pump that uses MsgWaitForMultipleObjects instead of PeekMessage.

There's a slight denial-of-service risk here, as a malicious process could create an event with the same name and cause your other application to exit.

If you need more sophisticated communication, you'll need a pipe, mailslot, shared memory, file watches, registry watches, or use another synchronizable kernel event (Mutex, Semaphore, etc.).

This works fine:

// msg.c:

#include <windows.h>
#include <stdio.h>

int CALLBACK WinMain (_In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) {
    MSG msg;
    DWORD curThreadId;

    curThreadId = GetCurrentThreadId();

    // Send messages to self:
    PostThreadMessage(curThreadId, WM_USER, 1, 2);
    PostThreadMessage(curThreadId, WM_USER+1, 3, 4);
    PostThreadMessage(curThreadId, WM_USER+2, 5, 6);
    PostThreadMessage(curThreadId, WM_USER+3, 7, 8);
    PostThreadMessage(curThreadId, WM_QUIT, 9, 10);

    while (GetMessage(&msg, NULL, 0, 0)) {
        printf("message: %d; wParam: %d; lParam: %d\n", msg.message, msg.wParam, msg.lParam);
    }

    return (int) msg.wParam;
}

Make:

> g++ -m64 -mwindows -c -o msg.o msg.c
> g++ -s -o msg.exe msg.o
> msg.exe
message: 1024; wParam: 1; lParam: 2
message: 1025; wParam: 3; lParam: 4
message: 1026; wParam: 5; lParam: 6
message: 1027; wParam: 7; lParam: 8

> echo %ERRORLEVEL%
9

If your IPC doesn't require any parameters, your service could implement a custom control code that its Handler/Ex() looks for, and then other apps can use ControlService() to send that control code to the service.

Though, shutting down a service programmably can be done using ControlService(SERVICE_CONTROL_STOP) instead. The service should shut itself down when its Handler/Ex() receives a SERVICE_CONTROL_STOP request.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM