windows - Go 语言设置 Windows 事件 Hook

标签 windows go

您好,我正在尝试在 go 中设置一个全局事件 Hook ,但我没有得到事件句柄或任何错误消息,请帮忙,下面是代码,从我下面的代码中,我希望从 SetWinEventHook 得到错误消息如果有的话,但它只会阻塞在 Logger.Println("procSetWinEventHook S")请注意我没有包括我的客户Logger但这不是障碍。

  package main

import(
    "fmt"
    "syscall"
    "unsafe"
    "log"
    "golang.org/x/sys/windows"
)

var(
    user32 = windows.NewLazyDLL("user32.dll")
    modkernel32 = windows.NewLazyDLL("kernel32.dll")

    procSetWinEventHook     = user32.NewProc("SetWinEventHook")
    procUnhookWinEvent      = user32.NewProc("UnhookWinEvent")
    procGetMessage = user32.NewProc("GetMessageW")
    procTranslateMessage = user32.NewProc("TranslateMessage")
    procDispatchMessage = user32.NewProc("DispatchMessageW")

    procGetModuleHandle            = modkernel32.NewProc("GetModuleHandleW")

    ActiveWinEventHook WINEVENTPROC = func (hWinEventHook HWINEVENTHOOK, event uint32, hwnd HWND, idObject int32, idChild int32, idEventThread uint32, dwmsEventTime uint32)  {
        log.Println("fond")

    }

)

type WINEVENTPROC func(hWinEventHook HWINEVENTHOOK, event uint32, hwnd HWND, idObject int32, idChild int32, idEventThread uint32, dwmsEventTime uint32) uintptr

type (
    HANDLE          uintptr
    HINSTANCE       HANDLE
    HHOOK       HANDLE
    HMODULE     HANDLE
    HWINEVENTHOOK HANDLE
    DWORD           uint32
    INT           int
    WPARAM           uintptr
    LPARAM uintptr
    LRESULT uintptr
    HWND HANDLE
    UINT uint32
    BOOL int32
    ULONG_PTR uintptr
    LONG                  int32
    LPWSTR                *WCHAR
    WCHAR                 uint16
)

type POINT struct {
    X, Y int32
}

type MSG struct {
    Hwnd    HWND
    Message uint32
    WParam  uintptr
    LParam  uintptr
    Time    uint32
    Pt      POINT
}


const (
    //~ EVENT_SYSTEM_FOREGROUND DWORD = 0x0003
    //~ WINEVENT_OUTOFCONTEXT  DWORD = 0x0000
    //~ WINEVENT_INCONTEXT   = 0x0004
    EVENT_SYSTEM_FOREGROUND  = 3
    WINEVENT_OUTOFCONTEXT   = 0
    WINEVENT_INCONTEXT   = 4
    WINEVENT_SKIPOWNPROCESS   = 2
    WINEVENT_SKIPOWNTHREAD   = 1
)

func main() {

    log.Println("starting")
    hinst := GetModuleHandle("")
    fmt.Println(hinst)

    winEvHook := SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, 0 , ActiveWinEventHook, 0, 0, WINEVENT_OUTOFCONTEXT|WINEVENT_SKIPOWNPROCESS )
    log.Println("Windows Event Hook: ")
    log.Println("Windows Event Hook: ", winEvHook)

    for {

        var msg MSG
        if m := GetMessage(&msg, 0, 0, 0); m != 0 {
            TranslateMessage(&msg)
            DispatchMessage(&msg)
       }
    }
    UnhookWinEvent(winEvHook)
    return

}


func SetWinEventHook(eventMin DWORD, eventMax DWORD, hmodWinEventProc HMODULE, pfnWinEventProc WINEVENTPROC, idProcess DWORD, idThread DWORD, dwFlags DWORD) HWINEVENTHOOK {
    log.Println("procSetWinEventHook S")
    ret, ret2 , err := procSetWinEventHook.Call(
        uintptr(eventMin),
        uintptr(eventMax),
        uintptr(hmodWinEventProc),
        pfnWinEventProcCallback,
        uintptr(idProcess),
        uintptr(idThread),
        uintptr(dwFlags),
    )

    log.Printf("%#v", err)
    log.Printf("%#v", ret)
    log.Printf("%#v", ret2)
    log.Println("procSetWinEventHook E")
    return HWINEVENTHOOK(ret)
}

func UnhookWinEvent(hWinEventHook HWINEVENTHOOK) bool {
    ret, _, _ := procUnhookWinEvent.Call(
        uintptr(hWinEventHook),
    )
    return ret != 0
}

func GetModuleHandle(modulename string) HINSTANCE {
    var mn uintptr
    if modulename == "" {
        mn = 0
    } else {
        mn = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(modulename)))
    }
    ret, _, _ := procGetModuleHandle.Call(mn)
    return HINSTANCE(ret)
}

func GetMessage(msg *MSG, hwnd HWND, msgFilterMin UINT, msgFilterMax UINT) int {
    ret, _, _ := procGetMessage.Call(
        uintptr(unsafe.Pointer(msg)),
        uintptr(hwnd),
        uintptr(msgFilterMin),
        uintptr(msgFilterMax))

    return int(ret)
}

func TranslateMessage(msg *MSG) bool {
    ret, _, _ := procTranslateMessage.Call(
        uintptr(unsafe.Pointer(msg)))
    return ret != 0
}

func DispatchMessage(msg *MSG) uintptr {
    ret, _, _ := procDispatchMessage.Call(
        uintptr(unsafe.Pointer(msg)))
    return ret
}

最佳答案

所以经过研究我注意到

syscall.NewCallback() 需要一个输出值,对于 WinEventProc 但是来自 MSDN,回调 WinEventProc 没有返回任何值,所以一个“强制”类型的返回值 uintptr 并且完美地工作。就像下面的代码:

package main

import(
    "fmt"
    "syscall"
    "unsafe"
    "log"
    "golang.org/x/sys/windows"
)

var(
    user32 = windows.NewLazyDLL("user32.dll")
    modkernel32 = windows.NewLazyDLL("kernel32.dll")

    procSetWinEventHook     = user32.NewProc("SetWinEventHook")
    procUnhookWinEvent      = user32.NewProc("UnhookWinEvent")
    procGetMessage = user32.NewProc("GetMessageW")
    procTranslateMessage = user32.NewProc("TranslateMessage")
    procDispatchMessage = user32.NewProc("DispatchMessageW")

    procGetModuleHandle            = modkernel32.NewProc("GetModuleHandleW")

    ActiveWinEventHook WINEVENTPROC = func (hWinEventHook HWINEVENTHOOK, event uint32, hwnd HWND, idObject int32, idChild int32, idEventThread uint32, dwmsEventTime uint32) uintptr  {
        log.Println("fond")

    }

)

type WINEVENTPROC func(hWinEventHook HWINEVENTHOOK, event uint32, hwnd HWND, idObject int32, idChild int32, idEventThread uint32, dwmsEventTime uint32) uintptr

type (
    HANDLE          uintptr
    HINSTANCE       HANDLE
    HHOOK       HANDLE
    HMODULE     HANDLE
    HWINEVENTHOOK HANDLE
    DWORD           uint32
    INT           int
    WPARAM           uintptr
    LPARAM uintptr
    LRESULT uintptr
    HWND HANDLE
    UINT uint32
    BOOL int32
    ULONG_PTR uintptr
    LONG                  int32
    LPWSTR                *WCHAR
    WCHAR                 uint16
)

type POINT struct {
    X, Y int32
}

type MSG struct {
    Hwnd    HWND
    Message uint32
    WParam  uintptr
    LParam  uintptr
    Time    uint32
    Pt      POINT
}


const (
    //~ EVENT_SYSTEM_FOREGROUND DWORD = 0x0003
    //~ WINEVENT_OUTOFCONTEXT  DWORD = 0x0000
    //~ WINEVENT_INCONTEXT   = 0x0004
    EVENT_SYSTEM_FOREGROUND  = 3
    WINEVENT_OUTOFCONTEXT   = 0
    WINEVENT_INCONTEXT   = 4
    WINEVENT_SKIPOWNPROCESS   = 2
    WINEVENT_SKIPOWNTHREAD   = 1
)

func main() {

    log.Println("starting")
    hinst := GetModuleHandle("")
    fmt.Println(hinst)

    winEvHook := SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, 0 , ActiveWinEventHook, 0, 0, WINEVENT_OUTOFCONTEXT|WINEVENT_SKIPOWNPROCESS )
    log.Println("Windows Event Hook: ")
    log.Println("Windows Event Hook: ", winEvHook)

    for {

        var msg MSG
        if m := GetMessage(&msg, 0, 0, 0); m != 0 {
            TranslateMessage(&msg)
            DispatchMessage(&msg)
       }
    }
    UnhookWinEvent(winEvHook)
    return

}


func SetWinEventHook(eventMin DWORD, eventMax DWORD, hmodWinEventProc HMODULE, pfnWinEventProc WINEVENTPROC, idProcess DWORD, idThread DWORD, dwFlags DWORD) HWINEVENTHOOK {
    log.Println("procSetWinEventHook S")
    pfnWinEventProcCallback := syscall.NewCallback(pfnWinEventProc)
    ret, ret2 , err := procSetWinEventHook.Call(
        uintptr(eventMin),
        uintptr(eventMax),
        uintptr(hmodWinEventProc),
        pfnWinEventProcCallback,
        uintptr(idProcess),
        uintptr(idThread),
        uintptr(dwFlags),
    )

    log.Printf("%#v", err)
    log.Printf("%#v", ret)
    log.Printf("%#v", ret2)
    log.Println("procSetWinEventHook E")
    return HWINEVENTHOOK(ret)
}

func UnhookWinEvent(hWinEventHook HWINEVENTHOOK) bool {
    ret, _, _ := procUnhookWinEvent.Call(
        uintptr(hWinEventHook),
    )
    return ret != 0
}

func GetModuleHandle(modulename string) HINSTANCE {
    var mn uintptr
    if modulename == "" {
        mn = 0
    } else {
        mn = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(modulename)))
    }
    ret, _, _ := procGetModuleHandle.Call(mn)
    return HINSTANCE(ret)
}

func GetMessage(msg *MSG, hwnd HWND, msgFilterMin UINT, msgFilterMax UINT) int {
    ret, _, _ := procGetMessage.Call(
        uintptr(unsafe.Pointer(msg)),
        uintptr(hwnd),
        uintptr(msgFilterMin),
        uintptr(msgFilterMax))

    return int(ret)
}

func TranslateMessage(msg *MSG) bool {
    ret, _, _ := procTranslateMessage.Call(
        uintptr(unsafe.Pointer(msg)))
    return ret != 0
}

func DispatchMessage(msg *MSG) uintptr {
    ret, _, _ := procDispatchMessage.Call(
        uintptr(unsafe.Pointer(msg)))
    return ret
}

关于windows - Go 语言设置 Windows 事件 Hook ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41559026/

相关文章:

html - 使用 CSS3 和 HTML5 制作小部件

c++ - 在 nVidia Optimus 中以编程方式选择集成显卡

c++ - 发出c++代码system()调用外部编译器编译其他c++代码

google-app-engine - 适用于Google AppEngine Go的Cloud IDE

c++ - 如何正确设置 Windows 路径以便 CMake 轻松识别?

c# - 如何等待C#中的ADB输出?

go - 在另一个例程中调用SetReadDeadline是否正确?

go - 如何构造 time.Time 与时区偏移

go - 将字符串解析为特定类型的 int(int8、int16、int32、int64)

Go:如何在 Go 中使用 func() bool 参数?