Go lang设置windows事件挂钩

时间:2017-01-09 23:58:26

标签: windows go

您正在尝试设置一个全局事件挂钩,但我没有得到事件句柄或任何错误消息,请帮助,下面是代码,从我的代码下面我期望得到来自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
}

1 个答案:

答案 0 :(得分:2)

经过研究后我发现了

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
}