首页 > 解决方案 > JNA 按名称从进程中获取模块

问题描述

我正在寻找一种在 Java 中从 C++ 重写函数的方法,在该函数中,我从进程的名称中获取模块条目。我在 JNA 方面的经验并不丰富,我很难理解指针是如何在 Java 中实现的。这是我的 C++ 代码。

ULONG GetModule(DWORD th32ProcessID, MODULEENTRY32* Entry, PCWSTR szModule) 
{
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, th32ProcessID);

    if (hSnapshot != INVALID_HANDLE_VALUE) 
{
    ULONG dwError = ERROR_NOT_FOUND;

    Entry->dwSize = sizeof(MODULEENTRY32);

    if (Module32FirstW(hSnapshot, Entry))
    {
        do 
        {
            if (!_wcsicmp(Entry->szModule, szModule))
            {
                dwError = NOERROR;
                break;
            }
        } while (Module32NextW(hSnapshot, Entry));
    }

    CloseHandle(hSnapshot);

    return dwError;
   }
   return GetLastError();
}

这是我在java中实现它的尝试:

    private Tlhelp32.MODULEENTRY32W findModule(String module) {
    Tlhelp32.MODULEENTRY32W moduleEntry = new Tlhelp32.MODULEENTRY32W.ByReference();

    WinNT.HANDLE snapshot =
            Kernel32.INSTANCE.CreateToolhelp32Snapshot(
                    TH32CS_SNAPMODULE,
                    new WinDef.DWORD(pid)
            );

    if(snapshot != INVALID_HANDLE_VALUE) {
        if(Kernel32.INSTANCE.Module32FirstW(snapshot, moduleEntry)) {
            do {
                if(Arrays.toString(moduleEntry.szModule).equals(module)) {
                    return moduleEntry;
                }
            } while (Kernel32.INSTANCE.Module32NextW(snapshot, moduleEntry));
        }
    }
    return null;
}

它总是返回 null。

标签: javapointerswinapijna

解决方案


我不认为你在Arrays.toString这里寻找。看看它的文档

返回指定数组内容的字符串表示形式。字符串表示由数组元素的列表组成,括在方括号 ("[]") 中。相邻元素由字符“,”(逗号后跟一个空格)分隔。通过 String.valueOf(char) 将元素转换为字符串。如果 a 为空,则返回“空”。

例如,一个char[]数组{ 'h', 'e', 'l', 'l', 'o' }将被字符串化为"[h, e, l, l, o]".

由于您只想将该 char 数组按原样转换为字符串,因此请尝试使用执行此操作的String类的构造函数

if (module.equals(new String(moduleEntry.szModule))) {
    // ...
}

如果您不是在寻找精确匹配,您可以尝试.contains().

另外,请记住在 C++ 版本中使用like关闭快照的句柄!CloseHandle如果您不关闭句柄,则您的方法每次调用时都会泄漏内存。

private Tlhelp32.MODULEENTRY32W findModule(String module) {
    Tlhelp32.MODULEENTRY32W moduleEntry = new Tlhelp32.MODULEENTRY32W.ByReference();

    WinNT.HANDLE snapshot = Kernel32.INSTANCE.CreateToolhelp32Snapshot(
        TH32CS_SNAPMODULE,
        new WinDef.DWORD(pid)
    );

    if (snapshot == INVALID_HANDLE_VALUE) {
        return null;
    }

    Tlhelp32.MODULEENTRY32W match = null;
    if (Kernel32.INSTANCE.Module32FirstW(snapshot, moduleEntry)) {
        do {
            if (module.equals(new String(moduleEntry.szModule))) {
                match = moduleEntry;
                break;
            }
        } while (Kernel32.INSTANCE.Module32NextW(snapshot, moduleEntry));
    }

    Kernel32.INSTANCE.CloseHandle(snapshot);
    return match;
}

推荐阅读