Skip to content

[Bug] x64 环境下进程遍历失败:进程名为空 #133

@feliciakalonji

Description

@feliciakalonji

Current ffi-rs version:^1.3.1

const { define, DataType, open,arrayConstructor, FFITypeTag } = require('ffi-rs');


// 1. 定义常量
const TH32CS_SNAPPROCESS = 0x00000002;
const INVALID_HANDLE_VALUE = -1;

// 2. 打开 kernel32.dll 并定义函数
// ffi-rs 使用对象映射的方式定义参数和返回值
open({ library: 'kernel32', path: 'kernel32.dll' });

const PROCESSENTRY32 = {
	dwSize: DataType.U32,
	cntUsage: DataType.U32,
	th32ProcessID: DataType.U32,
	// 将 External 改为 I64
	th32DefaultHeapID: DataType.I64,
	th32ModuleID: DataType.U32,
	cntThreads: DataType.U32,
	th32ParentProcessID: DataType.U32,
	pcPriClassBase: DataType.I32,
	dwFlags: DataType.U32,
	szExeFile: arrayConstructor({
		type: DataType.U8Array, // 使用 U8Array 对应 ANSI 字符
		length: 260,
		ffiTypeTag: FFITypeTag.StackArray
	})
};

const kernel32 = define({
	CreateToolhelp32Snapshot: {
		library: 'kernel32',
		retType: DataType.I64, // 句柄在 64 位系统上通常视为 i64
		paramsType: [DataType.U32, DataType.U32],
	},
	Process32First: {
		library: 'kernel32',
		retType: DataType.Boolean,
		paramsType: [DataType.I64, PROCESSENTRY32],
	},
	Process32Next: {
		library: 'kernel32',
		retType: DataType.Boolean,
		paramsType: [DataType.I64, PROCESSENTRY32],
	},
	CloseHandle: {
		library: 'kernel32',
		retType: DataType.Boolean,
		paramsType: [DataType.I64],
	}
});

// 3. 调用函数获取快照句柄
// 第一个参数是快照类型,第二个参数是进程 ID(0 表示当前系统所有进程)
const hSnapshot = kernel32.CreateToolhelp32Snapshot([TH32CS_SNAPPROCESS, 0]);
// 初始化结构体对象
const entry = {
	dwSize: 304, // x64 下 ANSI 结构体的正确尺寸
	cntUsage: 0,
	th32ProcessID: 0,
	padding: 0,        // 必须传值,不能省略
	th32DefaultHeapID: 0, // I64 必须使用 BigInt
	th32ModuleID: 0,
	cntThreads: 0,
	th32ParentProcessID: 0,
	pcPriClassBase: 0,
	dwFlags: 0,
	szExeFile: Buffer.alloc(260)
};

if (kernel32.Process32First([hSnapshot, entry])) {
	do {
		console.log(entry.szExeFile); //问题:这里恒为空
		// entry.szExeFile 现在是一个 Buffer,可以直接转换
		// const name = entry.szExeFile.toString('utf-8').replace(/\0/g, '');
		// if (name) {
		// 	console.log(`PID: ${entry.th32ProcessID}\t Name: ${name}`);
		// }
	} while (kernel32.Process32Next([hSnapshot, entry]));
}

if (hSnapshot === BigInt(INVALID_HANDLE_VALUE)) {
	console.error('无法创建进程快照');
	return;
}

console.log(`成功获取快照句柄: ${hSnapshot}`);

// 4. 操作完成后必须关闭句柄防止内存泄漏
const closed = kernel32.CloseHandle([hSnapshot]);
console.log(`句柄关闭状态: ${closed}`);

问题描述
在 Windows x64 环境下使用 ffi-rs 调用 CreateToolhelp32Snapshot 和 Process32First/Next 时,遇到以下问题:
数据截断/偏移:获取到的进程名(szExeFile)为空字符串或乱码。

环境信息
操作系统: Windows 10/11 x64

库版本: ffi-rs

Node.js: v16+

架构: x64(此架构下的内存对齐规则是问题的根本原因)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions