调用Windows的SendMessageW函数从GO语言中永远不会返回。

huangapple go评论91阅读模式
英文:

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() 后没有返回,没有错误,并且我看不到 ab 的输出。我必须使用 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 &quot;github.com/sirupsen/logrus&quot;
    
    	&quot;golang.org/x/sys/windows&quot;
    )
    
    func main() {
    	user32DLL := windows.NewLazyDLL(&quot;user32.dll&quot;)
    	procSendMsg := user32DLL.NewProc(&quot;SendMessageW&quot;)
    
    	a, b, err := procSendMsg.Call(0xFFFF, 0x0112, 0xF170, 2)
    	if err != nil {
    		log.Errorf(&quot;Error returned from SendMsg: %v&quot;, err)
    	}
    	log.Infof(&quot;a = %v, b = %v:&quot;, a, b)
    }

The program does work (IE&gt; the monitor turns off), but never returns from the procSendMsg.Call() -- no errors, and I never see the output of &#39;a&#39; and &#39;b&#39;. I have to Ctrl-C to get out of the program.

Obviously I&#39;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 &quot;[DllImport(&quot;&quot;user32.dll&quot;&quot;)]`npublic static extern int SendMessage(int hWnd, int hMsg, int wParam, int lParam);&quot; -Name &quot;Win32SendMessage&quot; -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 &#39;scrnsave.scr /s&#39; to just blank the screen.
    //
    //  John D. Allen
    //  September, 2022
    //
    
    import (
    	&quot;strings&quot;
    
    	log &quot;github.com/sirupsen/logrus&quot;
    
    	&quot;golang.org/x/sys/windows&quot;
    )
    
    func main() {
    	user32DLL := windows.NewLazyDLL(&quot;user32.dll&quot;)
    	procPostMsg := user32DLL.NewProc(&quot;PostMessageW&quot;)
    
    	_, _, err := procPostMsg.Call(0xFFFF, 0x0112, 0xF170, 2)
    
    	//
    	// I get a &quot;Access is denied.&quot; 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 &amp;&amp; !strings.Contains(err.Error(), &quot;Access is denied.&quot;) {
    		log.Errorf(&quot;Error returned from PostMsg(): %v&quot;, err)
    	}
    }




</details>



huangapple
  • 本文由 发表于 2022年9月8日 22:26:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/73650720.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定