#winapi #node-ffi
#winapi #узел-ffi
Вопрос:
Я пытался использовать EnumProcesses
с node-ffi
. Я получил код ниже:
import ffi from 'ffi'
export const psapi = ffi.Library('psapi', {
EnumProcesses: ['bool', ['ulong', 'ulong', 'uint16*']]
})
export class Win32ProcessManager {
public async getProcessList () {
let lpidProcess = ref.alloc('ulong*')
const cb = 1024
const lpcbNeeded = ref.alloc('uint16*')
const res = psapi.EnumProcesses(lpidProcess, cb, lpcbNeeded)
const ulongSize = (ref as any).sizeof.ulong
const totalBytesReturned = lpcbNeeded.readInt16LE()
const processCount = totalBytesReturned / ulongSize
console.log(`processCount: ${processCount}`)
// ??? How to get the value from the lpidProcess?
return lpidProcess
}
}
Я пытался с ref.get
, но столкнулся с ошибками:
let processId = ref.get(array, 0, ref.types.ulong)
console.log(processId)
const pointerSize = (ref as any).sizeof.pointer
console.log(pointerSize)
let processId2 = ref.get(array, (ref as any).sizeof.pointer, ref.types.ulong)
console.log(processId2)
Ошибки:
RangeError [ERR_BUFFER_OUT_OF_BOUNDS]: Attempt to write outside buffer bounds
Кто-нибудь знает, как использовать node-ffi
чтение данных массива из dll?
Комментарии:
1. Вам нужно использовать достаточно большой массив вместо указателя (который может содержать только 1 элемент), потому что трудно предсказать, сколько процессов будет во время вашего вызова
EnumProcesses
. Кстати, вы объявили тип параметра равнымulong
, но передалиulong*
, возможно, вы могли бы использоватьref-array
, а затем передать count_of_array * sizeof_each_element в качестве 2-го параметра.2. @DrakeWu-MSFT Спасибо за ваш комментарий! Вы спасли мне жизнь! Вчера я потратил целый день, чтобы решить эту проблему.
3. NP, и вы можете поделиться своим решением в качестве ответа и не стесняйтесь принимать его самостоятельно.
4. Опубликован окончательный код: P
Ответ №1:
Спасибо @DrakeWu-MSFT, я наконец-то получил свой код, вот как они выглядят, наконец:
import ffi from 'ffi';
import ref from 'ref';
import ArrayType from "ref-array";
export const psapi = ffi.Library('psapi', {
EnumProcesses: ['bool', ['ulong*', 'ulong', 'uint16*']],
});
export class Win32ProcessManager {
public getProcessIdList (): number[] {
const processIdLength = 1024;
const ulongSize = (ref as any).sizeof.ulong;
const cb = processIdLength * ulongSize;
let processIdArray = ArrayType('ulong', processIdLength);
let lpidProcess = ref.alloc(processIdArray);
const lpcbNeeded = ref.alloc('uint16*');
const res = psapi.EnumProcesses(lpidProcess, cb, lpcbNeeded);
if (res) {
const totalBytesReturned = lpcbNeeded.readInt16LE();
const processCount = totalBytesReturned / ulongSize;
const processArray = (lpidProcess as any).deref();
let resultProcessArray: number[] = [];
for (let i = 0; i < processCount; i ) {
resultProcessArray.push(processArray[i]);
}
return resultProcessArray;
} else {
console.error(`Get process list failed with result from EnumProcess: ${res}`);
return [];
}
}
}
Я боролся с получением данных массива из указателя, и это было неправильно, как сказал @DrakeWu-MSFT в комментарии, потому что я не выделил достаточно места для буфера, никакие данные не могут быть записаны в это. С ref-array
и указателем на массив это работает как шарм.
Комментарии:
1. Небольшая проблема,
cb
должна быть длина массива (1024) * ulongSize , хотя 1024 достаточно для большинства случаев.2. И вы также можете не стесняться принимать свои собственные ответы .