英文:
Calling Windows SendMessageW from GOlang never returns
问题
尝试编写一个非常简单的用于关闭 Windows 显示器的 GO 程序。代码如下:
//go:build windows
// +build windows
package main
import (
log "github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
)
func main() {
user32DLL := windows.NewLazyDLL("user32.dll")
procSendMsg := user32DLL.NewProc("SendMessageW")
a, b, err := procSendMsg.Call(0xFFFF, 0x0112, 0xF170, 2)
if err != nil {
log.Errorf("Error returned from SendMsg: %v", err)
}
log.Infof("a = %v, b = %v:", a, b)
}
该程序确实可以工作(即关闭显示器),但是在 procSendMsg.Call()
后没有返回,没有错误,并且我看不到 a
和 b
的输出。我必须使用 Ctrl-C 来退出程序。
显然,我在调用 user32.dll
函数方面做错了什么...这是我第一次尝试使用 GO 编写 Windows 程序。
我做错了什么?
[提示:我从这个 PowerShell 脚本中得到了灵感:
(Add-Type -MemberDefinition "[DllImport(""user32.dll"")]`npublic static extern int SendMessage(int hWnd, int hMsg, int wParam, int lParam);" -Name "Win32SendMessage" -Namespace Win32Functions -PassThru)::SendMessage(0xffff, 0x0112, 0xF170, 2)
]
谢谢你的反馈!
<details>
<summary>英文:</summary>
Trying to write a very simple GO program for Windows that turns off the monitor. The code looks like this:
//go:build windows
// +build windows
package main
import (
log "github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
)
func main() {
user32DLL := windows.NewLazyDLL("user32.dll")
procSendMsg := user32DLL.NewProc("SendMessageW")
a, b, err := procSendMsg.Call(0xFFFF, 0x0112, 0xF170, 2)
if err != nil {
log.Errorf("Error returned from SendMsg: %v", err)
}
log.Infof("a = %v, b = %v:", a, b)
}
The program does work (IE> the monitor turns off), but never returns from the procSendMsg.Call() -- no errors, and I never see the output of 'a' and 'b'. I have to Ctrl-C to get out of the program.
Obviously I'm doing something wrong w.r.t. calling the user32.dll function...this IS my first attempt at writing a Windows program with GO.
What am I doing wrong?
[FYI: I got the idea from this PowerShell script:
(Add-Type -MemberDefinition "[DllImport(""user32.dll"")]`npublic static extern int SendMessage(int hWnd, int hMsg, int wParam, int lParam);" -Name "Win32SendMessage" -Namespace Win32Functions -PassThru)::SendMessage(0xffff, 0x0112, 0xF170, 2)
]
Thanks for your feedback!!
</details>
# 答案1
**得分**: 1
FYI:这是工作版本。
//go:build windows
// +build windows
package main
//
// turnOffMonitor -- 关闭Windows上的显示器信号。相比使用'scrnsave.scr /s'只是屏幕变黑,这是更好的省电方式。
//
// John D. Allen
// 2022年9月
//
import (
"strings"
log "github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
)
func main() {
user32DLL := windows.NewLazyDLL("user32.dll")
procPostMsg := user32DLL.NewProc("PostMessageW")
_, _, err := procPostMsg.Call(0xFFFF, 0x0112, 0xF170, 2)
//
// 当我以没有SYSTEM权限的用户运行时,我会收到“拒绝访问”的错误...但出于某种原因它仍然可以工作。
if err != nil && !strings.Contains(err.Error(), "Access is denied.") {
log.Errorf("从PostMsg()返回的错误:%v", err)
}
}
<details>
<summary>英文:</summary>
FYI: Here is the working version.
//go:build windows
// +build windows
package main
//
// turnOffMonitor -- Shuts down the signal to the monitor on Windows. A better power saver
// over using 'scrnsave.scr /s' to just blank the screen.
//
// John D. Allen
// September, 2022
//
import (
"strings"
log "github.com/sirupsen/logrus"
"golang.org/x/sys/windows"
)
func main() {
user32DLL := windows.NewLazyDLL("user32.dll")
procPostMsg := user32DLL.NewProc("PostMessageW")
_, _, err := procPostMsg.Call(0xFFFF, 0x0112, 0xF170, 2)
//
// I get a "Access is denied." error when I run this from a user that does
// not have SYSTEM rights...but it still works anyway for some reason.
if err != nil && !strings.Contains(err.Error(), "Access is denied.") {
log.Errorf("Error returned from PostMsg(): %v", err)
}
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论