能,但需用WM_COPYDATA等系统支持的消息;自定义消息(如WM_USER+1)若对方未注册处理则被忽略,且SendMessage同步阻塞风险高。

SendMessage 能不能跨进程发自定义消息?
不能直接用 SendMessage 向其他进程的窗口发送自定义消息(比如 WM_USER + 1),除非对方明确注册并处理该消息,且双方使用相同的编译器/ABI、对结构体内存布局一致。Windows 本身不校验消息合法性,但目标进程若未实现对应 WndProc 分支,消息会被丢弃或触发默认处理(通常是忽略)。
更关键的是:如果目标窗口属于另一个进程,SendMessage 会**同步等待对方处理完再返回**,一旦对方卡住、崩溃或没响应,你的进程也会被挂起 —— 这是跨进程调用中最容易被忽略的风险点。
怎么安全地让另一进程收到你的自定义数据?
推荐用 Windows 提供的跨进程通信机制替代“强行发自定义消息”。实际开发中,以下方式更可靠:
-
WM_COPYDATA:唯一被系统明确支持用于跨进程传递小段数据的窗口消息。接收方无需提前注册,只要在WndProc中处理WM_COPYDATA即可;发送方构造COPYDATASTRUCT,把数据指针和长度填进去,调用SendMessage发送即可 - 共享内存(
CreateFileMapping+MapViewOfFile):适合频繁、大量数据交换,需自行加锁(如CreateMutex)避免竞态 - 命名管道(
CreateNamedPipe):比共享内存更易控制读写方向和生命周期,适合命令-响应类交互
别试图用 RegisterWindowMessage 来“标准化”自定义消息 —— 它只保证消息 ID 在本机全局唯一,不解决数据序列化、内存布局、线程安全等问题。
立即学习“C++免费学习笔记(深入)”;
WM_COPYDATA 实操要点
这是最轻量、最常用、也最容易踩坑的方式:
- 发送方必须确保
COPYDATASTRUCT.dwData和.cbData值合法,.lpData指向的内存**在 SendMessage 返回前不能释放**(因为是同步拷贝,不是异步复制) - 接收方收到
WM_COPYDATA后,lParam是COPYDATASTRUCT*,其lpData指向的是发送方进程地址空间中的内存 —— 你只能读,不能写,也不能保存该指针长期使用 - 字符串建议用 UTF-8 或 UTF-16 显式编码,避免接收方按不同代码页解析出错
- 示例片段(发送端):
COPYDATASTRUCT cds = {}; cds.dwData = 123; // 自定义标识 cds.cbData = (lstrlen(text) + 1) * sizeof(wchar_t); cds.lpData = (void*)text; SendMessage(hwndTarget, WM_COPYDATA, (WPARAM)hwndSender, (LPARAM)&cds);
为什么 PostMessage 不行?
PostMessage 虽然不会阻塞,但它**不支持跨进程传递指针型参数**(如 lParam 指向的数据)。当你用 PostMessage 发送 WM_USER+1 并附带一个本进程的指针,目标进程解引用时会访问非法地址,大概率触发 ACCESS_VIOLATION。系统不会帮你做内存映射或序列化 —— 这不是设计缺陷,而是安全边界。
真正需要异步通信时,应改用命名事件(CreateEvent)通知对方“数据已就绪”,再配合共享内存或管道读取内容。
跨进程消息的本质不是“怎么发”,而是“怎么让对方安全地拿到你的真实意图”。绕过序列化和边界检查去硬传指针,等于主动打开崩溃开关。


















