我是 JNA 的新手,在尝试我的第一个程序来列出 Windows 上的所有进程时,我遇到了一些麻烦。出于某种原因,我得到以下输出:
[pid = 0, name = ???????? ]
[pid = 4, name = ???????? ]
[pid = 364, name = ???????? ]
[pid = 516, name = ????e??? ]
[pid = 648, name = ?????e?? ]
[pid = 668, name = ????ee?? ]
[pid = 708, name = ???????? ]
[pid = 732, name = ????e??? ]
[pid = 740, name = ???ee??? ]
[pid = 796, name = ???????? ]
[pid = 880, name = ?????e?? ]
...
进程标识符是有效的,并且在快照期间当前正在我的系统上运行,但由于某种原因,字符串已损坏。 StackOverflow 上的其他几个类似示例给了我相同的结果。我是否需要在最新版本的 JNA 中指定一些新的东西才能让这样的程序工作?
public class Processes
{
private static final Kernel32 kernel = ( Kernel32 )Native.loadLibrary( Kernel32.class );
public static ArrayList<Process> getSnapshot( ) throws LastErrorException
{
ArrayList<Process> processes = new ArrayList<Process>( );
HANDLE snapshot = null;
try
{
snapshot = kernel.CreateToolhelp32Snapshot( Tlhelp32.TH32CS_SNAPPROCESS, new DWORD( 0 ) );
PROCESSENTRY32 entry = new PROCESSENTRY32( );
kernel.Process32First( snapshot, entry );
do
{
processes.add( new Process( Native.toString( entry.szExeFile ), entry.th32ProcessID.intValue() ) );
}
while( kernel.Process32Next( snapshot, entry ) );
}
finally
{
kernel.CloseHandle( snapshot );
}
return processes;
}
}
我的代码很大程度上基于 MSDN 示例 here .
最佳答案
您缺少 Native.loadLibrary
的选项来告诉 JNA 自动映射到 Process32FirstW
(W32APIOptions.DEFAULT_OPTIONS
会为您做这件事).查看 JNA 本身如何加载 kernel32
库。
JNA 的 platform.jar
中包含的 Process32First
的定义实际上仅与 unicode (-W
) 版本由于 PROCESSENTRY32
结构的定义,它使用 Java char
作为文件名。你变得垃圾的原因是“ANSI”版本的编码字节数组已被读入 Java char
数组。 Native.toString()
正在尝试从该数组中读取数据,但没有意识到数据最初是编码字节。
关于Java JNA : PROCESSENTRY32. szExeFile 转换为 Java 字符串时返回 "????...",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34553440/