You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言调用Windows SendMessageW函数无法返回的问题排查

问题原因及解决方案

问题根源

你使用的SendMessageW是Windows API中的阻塞式消息发送函数:它会将消息发送给目标窗口(这里是广播给所有顶层窗口0xFFFF),并等待所有接收窗口处理完消息后才会返回。如果系统中存在某个窗口未及时响应或处理该消息,你的程序就会一直卡在procSendMsg.Call()调用处,无法执行后续代码。

解决方案

改用非阻塞式的PostMessageW函数替代SendMessageW。PostMessageW仅将消息放入目标窗口的消息队列就立即返回,无需等待消息处理完成,完全避免了阻塞问题。

修改后的代码如下:

//go:build windows
// +build windows

package main

import (
    log "github.com/sirupsen/logrus"
    "golang.org/x/sys/windows"
)

const (
    WM_SYSCOMMAND   = 0x0112
    SC_MONITORPOWER = 0xF170
)

func main() {
    user32DLL := windows.NewLazyDLL("user32.dll")
    procPostMsg := user32DLL.NewProc("PostMessageW")

    // 使用windows.HWND_BROADCAST替代直接写0xFFFF,更符合规范
    ret, _, err := procPostMsg.Call(
        uintptr(windows.HWND_BROADCAST),
        uintptr(WM_SYSCOMMAND),
        uintptr(SC_MONITORPOWER),
        uintptr(2),
    )

    if ret == 0 {
        log.Errorf("PostMessage调用失败: %v", err)
    } else {
        log.Infof("消息发送成功,显示器已关闭")
    }
}

补充说明

  • HWND_BROADCAST(值为0xFFFF)表示将消息广播给所有顶层窗口,使用windows.HWND_BROADCAST常量比直接写十六进制值更具可读性和规范性。
  • SC_MONITORPOWER参数的取值:2代表关闭显示器,1代表打开显示器,-1代表将显示器切换到低功耗模式。
  • PowerShell中的SendMessage调用看似正常返回,是因为.NET的P/Invoke封装在特定环境下未遇到阻塞窗口,但这并非通用可靠的实现方式,使用PostMessageW才是处理这类广播消息的正确姿势。

内容的提问来源于stack exchange,提问作者JD Allen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:45:33