Kotlin/Native 读取进程内存

主要步骤

通过 CreateToolhelp32Snapshot 遍历进程并获取进程 id

代码

Copy
private fun getProcessID(processName: String): UInt{
memScoped {
val snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS.toUInt(),0U)
val processEntry = alloc<PROCESSENTRY32W>()
processEntry.dwSize = sizeOf<PROCESSENTRY32W>().convert()
if(Process32FirstW(snapshot,processEntry.ptr) != 0){
do {
val name = processEntry.szExeFile.toKString()
if(processName == name){
CloseHandle(snapshot)
return processEntry.th32ProcessID
}
}while (Process32NextW(snapshot,processEntry.ptr) != 0)
}
CloseHandle(snapshot)
return 0U
}
}

遇到的坑

1. 没有 CreateToolhelp32Snapshot 方法

原因：

默认没有导入 tlhelp32.h 头文件

解决办法：

创建路径nativeInterop/cinterop 并放入 windows.def :

Copy
package = platform.windows
headers = wtypes.h minwindef.h windows.h commctrl.h dwmapi.h shlobj.h shlwapi.h shobjidl.h \
urlmon.h usp10.h uxtheme.h vfw.h wininet.h winsock2.h ws2tcpip.h ws2def.h windows.h tlhelp32.h
compilerOpts = -DUNICODE -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -DWINAPI_FAMILY=3 -DOEMRESOURCE \
-Wno-incompatible-pointer-types -Wno-deprecated-declarations
linkerOpts = -lcomctl32 -lcrypt32 -lshlwapi -lshell32 -limm32 -lusp10 -lwininet -lgdi32 -luser32 -lkernel32 -lbcrypt -luuid -ldwmapi
noStringConversion = LoadCursorA LoadBitmapA LoadIconA LoadImageA LoadCursorW LoadBitmapW LoadIconW LoadImageW
depends = posix

路径图 :

windows.def 的来源：

windows.def 在此文件的 headers 后 加入 windows.h tlhelp32.h

在 build.gradle.kts 加入:

Copy
compilations.getByName("main"){
cinterops{
val windows by creating
}
}

:::

2. 获取不到进程

原先使用的是 Process32First和Process32Next 这两个方法去处理 CreateToolhelp32Snapshot 在 Process32First 的得到的结果为 0，正常来讲不应该为 0。随后我在 YouTrack 发了Issue

得到的解决办法是更换方法：

PROCESSENTRY32 -> PROCESSENTRY32W

Process32First -> Process32FirstW

Process32Next -> Process32NextW

在此感谢几位工作人员帮忙解决问题

参考文章

Create an app using C Interop and libcurl
[Kotlin/Native] Unable to get process via CreateToolhelp32Snapshot