从nodejs调用Windows SetWinEventHook

时间:2018-12-14 01:37:07

标签: node.js windows ffi

我正在尝试按照SetWinEventHook的描述调用here for C#,但要从nodejs调用。

我正在使用ffi-napi绑定到该函数。到目前为止,这是我的代码:

const ffi = require("ffi-napi")

const user32 = ffi.Library("user32", {
    SetWinEventHook: ["int", ["int", "int", "pointer", "pointer", "int", "int", "int"]]
})

const pfnWinEventProc = ffi.Callback("void", ["pointer", "int", "pointer", "long", "long", "int", "int"],
    function (hWinEventHook, event, hwnd, idObject, idChild, idEventThread, dwmsEventTime) {
        console.log("Callback!")
        console.log(arguments)
    })

const EVENT_SYSTEM_FOREGROUND = 3
const WINEVENT_OUTOFCONTEXT = 0
const WINEVENT_SKPIOWNPROCESS = 2

user32.SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, null, pfnWinEventProc,
    0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKPIOWNPROCESS)

setInterval(function () {
    // keep the script alive
}, 500)

process.on("exit", function () {
    console.log("Exiting")
    pfnWinEventProc
})

问题仅仅是我的回调没有被调用。每当更改焦点窗口时都应调用它。

我也没有收到任何错误,因此我对自己在这里做错的事情很迷茫。

如果要签出,代码也是here

1 个答案:

答案 0 :(得分:0)

我终于结合使用cluster module(如果您不想用消息循环阻止事件循环)并浏览Windows part of the active-win package

完整代码为here

const ffi = require("ffi-napi")
const cluster = require("cluster")
const ref = require("ref")
const wchar = require("ref-wchar")

if (cluster.isMaster) {
    console.log("Main code here...")
    cluster.fork()
} else {
    const msgType = ref.types.void
    const msgPtr = ref.refType(msgType)
    const EVENT_SYSTEM_FOREGROUND = 3
    const WINEVENT_OUTOFCONTEXT = 0
    const WINEVENT_SKPIOWNPROCESS = 2

    const user32 = ffi.Library("user32", {
        SetWinEventHook: ["int", ["int", "int", "pointer", "pointer", "int", "int", "int"]],
        GetWindowTextW: ["int", ["pointer", "pointer", "int"]],
        GetWindowTextLengthW: ["int", ["pointer"]],
        GetMessageA: ["bool", [msgPtr, "int", "uint", "uint"]]
    })

    function getMessage() {
        return user32.GetMessageA(ref.alloc(msgPtr), null, 0, 0)
    }

    const pfnWinEventProc = ffi.Callback("void", ["pointer", "int", "pointer", "long", "long", "int", "int"],
        function (hWinEventHook, event, hwnd, idObject, idChild, idEventThread, dwmsEventTime) {
            const windowTitleLength = user32.GetWindowTextLengthW(hwnd)
            const bufferSize = windowTitleLength * 2 + 4
            const titleBuffer = Buffer.alloc(bufferSize)
            user32.GetWindowTextW(hwnd, titleBuffer, bufferSize)
            const titleText = ref.reinterpretUntilZeros(titleBuffer, wchar.size)
            const finallyWindowTitle = wchar.toString(titleText)
            console.log(finallyWindowTitle)
        }
    )

    user32.SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, null, pfnWinEventProc,
        0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKPIOWNPROCESS)

    let res = getMessage()
    while(res != 0) {
        switch (res) {
            case -1:
                console.log("Invalid GetMessageA arguments or something!");
                break
            default:
                console.log("Got a message!")
        }
        res = getMessage()
    }
}