koffi-遍历桌面返回所有窗口的句柄
例子 desktop.js
js
const koffi = require("koffi");
// 加载user32.dll
const user32 = koffi.load("user32.dll");
// 定义 HANDLE 和 HWND
const HANDLE = koffi.pointer("HANDLE", koffi.opaque());
const HWND = koffi.alias("HWND", HANDLE);
// 定义 EnumWindowsProc 回调函数的签名
const EnumWindowsProc = koffi.proto(
"bool __stdcall EnumWindowsProc(HWND hwnd, long lParam)"
);
const EnumWindows = user32.func("__stdcall", "EnumWindows", "bool", [
koffi.pointer(EnumWindowsProc),
"int",
]);
let cb1 = koffi.register((hwnd, lParam) => {
console.log("[hwnd, lParam]", hwnd, lParam);
return true;
}, koffi.pointer(EnumWindowsProc));
EnumWindows(cb1, 0);
koffi.unregister(cb1);
console.log("EnumWindowsProc", EnumWindowsProc);
desktop.js 执行结果
powershell
PS C:\Users\Administrator\Desktop\koffi-sample> node .\desktop.js
[hwnd, lParam] [External: 180040] 0
[hwnd, lParam] [External: 1d071c] 0
[hwnd, lParam] [External: 101dc] 0
[hwnd, lParam] [External: 10190] 0
[hwnd, lParam] [External: 140474] 0
[hwnd, lParam] [External: 40974] 0
...
[hwnd, lParam] [External: 10104] 0
[hwnd, lParam] [External: 200a8] 0
[hwnd, lParam] [External: 200ac] 0
[hwnd, lParam] [External: 200b2] 0
[hwnd, lParam] [External: 3003c] 0
[hwnd, lParam] [External: 1016e] 0
[hwnd, lParam] [External: 3006e] 0
[hwnd, lParam] [External: b04a8] 0
[hwnd, lParam] [External: 407b0] 0
EnumWindowsProc [External: 1a3f3d38388]
PS C:\Users\Administrator\Desktop\koffi-sample>
下面是代码 desktop.js
带有详细中文注释的版本,帮助理解每个部分的作用以及它的返回值:
javascript
// 引入 koffi 库,用于调用本地系统库函数
const koffi = require("koffi");
// 加载 user32.dll,这是 Windows 系统用于管理窗口的系统库
const user32 = koffi.load("user32.dll");
// 定义 HANDLE 类型,表示一个通用的句柄,使用不透明的指针类型
const HANDLE = koffi.pointer("HANDLE", koffi.opaque());
// 定义 HWND 类型作为 HANDLE 的别名,特别表示窗口句柄
const HWND = koffi.alias("HWND", HANDLE);
// 定义 EnumWindowsProc 回调函数的签名,这是 EnumWindows 函数将调用的函数类型
const EnumWindowsProc = koffi.proto(
"bool __stdcall EnumWindowsProc(HWND hwnd, long lParam)"
);
// 声明 EnumWindows 函数,这是 user32.dll 中的一个函数,用于枚举所有顶层窗口
const EnumWindows = user32.func("__stdcall", "EnumWindows", "bool", [
koffi.pointer(EnumWindowsProc), // 回调函数的指针
"int", // 附加参数,传递给回调函数
]);
// 注册一个回调函数,用于 EnumWindows 调用
let cb1 = koffi.register((hwnd, lParam) => {
// 在控制台打印每个窗口的句柄和 lParam 值
console.log("[hwnd, lParam]", hwnd, lParam);
return true; // 返回 true 继续枚举窗口,返回 false 则停止枚举
}, koffi.pointer(EnumWindowsProc));
// 调用 EnumWindows 函数,传递注册的回调函数和 lParam 值 0
EnumWindows(cb1, 0);
// 注销回调函数,清理资源
koffi.unregister(cb1);
// 打印 EnumWindowsProc 函数的指针信息
console.log("EnumWindowsProc", EnumWindowsProc);
执行结果解释
- 执行
node .\desktop.js
命令时,控制台打印出的信息包括多个窗口句柄和 lParam 值。这些值是 EnumWindows 函数枚举到的顶层窗口的句柄,其中lParam
总是 0,因为在调用时传递的是 0。 [External: xxxxxx]
格式的输出表示窗口句柄,这是一个指向内存地址的指针。- 最后打印的
EnumWindowsProc [External: xxxxxxxxx]
表示回调函数指针的内部表示。
返回值
EnumWindows
函数:返回值是bool
类型,如果函数成功枚举所有窗口,通常返回true
。如果在枚举过程中回调函数返回了false
,则提前终止枚举并返回false
。- 回调函数
cb1
:每次调用时返回true
,表示继续枚举窗口。如果要停止枚举窗口,可以改为返回false
。
这个例子演示了如何使用 koffi
库与 Windows 的系统函数交互,特别是如何操作窗口句柄并在 Node.js 环境中执行系统级操作。
希望返回 hwnd 的值为 int32 类型
desktop.js
js
const koffi = require("koffi");
// 加载user32.dll
const user32 = koffi.load("user32.dll");
// 定义 HANDLE 和 HWND
const HANDLE = koffi.pointer("HANDLE", koffi.opaque());
const HWND = koffi.alias("HWND", HANDLE);
// 定义 EnumWindowsProc 回调函数的签名
const EnumWindowsProc = koffi.proto(
"bool __stdcall EnumWindowsProc(HWND hwnd, long lParam)"
"bool __stdcall EnumWindowsProc(int32, int32)"
);
const EnumWindows = user32.func("__stdcall", "EnumWindows", "bool", [
koffi.pointer(EnumWindowsProc),
"int",
]);
let cb1 = koffi.register((hwnd, lParam) => {
console.log("[hwnd, lParam]", hwnd, lParam);
return true;
}, koffi.pointer(EnumWindowsProc));
EnumWindows(cb1, 0);
koffi.unregister(cb1);
console.log("EnumWindowsProc", EnumWindowsProc);
代码执行结果
powershell
PS C:\Users\Administrator\Desktop\koffi-sample> node .\desktop.js
[hwnd, lParam] 1572928 0
[hwnd, lParam] 1902364 0
[hwnd, lParam] 66012 0
[hwnd, lParam] 65936 0
[hwnd, lParam] 1311860 0
[hwnd, lParam] 264564 0
[hwnd, lParam] 65796 0
[hwnd, lParam] 131240 0
...
[hwnd, lParam] 1377560 0
[hwnd, lParam] 65902 0
[hwnd, lParam] 196718 0
[hwnd, lParam] 722088 0
[hwnd, lParam] 264112 0
EnumWindowsProc [External: 1f4a5b35908]
PS C:\Users\Administrator\Desktop\koffi-sample>
以下是带中文注释的代码解释:
这段代码通过 koffi
库在 Node.js 环境中调用 Windows 系统库 user32.dll
的功能,用于枚举所有顶层窗口的句柄。
javascript
// 引入 koffi 库以便调用 Windows 的系统库函数
const koffi = require("koffi");
// 加载 Windows 的 user32.dll,这个库包含操作窗口的函数
const user32 = koffi.load("user32.dll");
// 定义 HANDLE 类型和 HWND 类型,HANDLE 是通用句柄,HWND 是窗口句柄
const HANDLE = koffi.pointer("HANDLE", koffi.opaque());
const HWND = koffi.alias("HWND", HANDLE);
// 定义 EnumWindowsProc 回调函数的签名,使用 int32 替代 HWND 类型来表示窗口句柄
const EnumWindowsProc = koffi.proto(
"bool __stdcall EnumWindowsProc(int32, int32)" // 签名中使用 int32 表示窗口句柄和附加参数
);
// 定义 EnumWindows 函数,此函数用于枚举所有顶层窗口
const EnumWindows = user32.func("__stdcall", "EnumWindows", "bool", [
koffi.pointer(EnumWindowsProc), // 指向回调函数的指针
"int", // 传递给回调函数的附加参数
]);
// 注册回调函数,当 EnumWindows 调用此函数时,打印窗口句柄和 lParam
let cb1 = koffi.register((hwnd, lParam) => {
console.log("[hwnd, lParam]", hwnd, lParam); // 打印窗口句柄和附加参数
return true; // 返回 true 继续枚举,返回 false 则停止枚举
}, koffi.pointer(EnumWindowsProc));
// 调用 EnumWindows 函数,开始枚举窗口
EnumWindows(cb1, 0);
// 注销回调函数,释放资源
koffi.unregister(cb1);
// 打印回调函数的签名信息,显示为外部引用
console.log("EnumWindowsProc", EnumWindowsProc);
注释说明
- 代码修改了回调函数的参数类型,从
HWND
改为int32
,这意味着窗口句柄被处理为普通的 32 位整数,而非特定的指针类型。这样做的目的是为了简化数据处理或适应特定的编程需求。 - 回调函数打印窗口句柄和
lParam
,窗口句柄现在是以整数形式直接打印,而不是作为外部或不透明的指针。
代码执行结果
- 执行结果显示了多个窗口的句柄和传递的参数(始终为 0),窗口句柄以整数形式展示,符合
int32
类型的期望表现。 - 这种方式使得处理窗口句柄的数据更为直接,适用于需要以数值方式操作或记录窗口句柄的场景。