我是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;
}
}
我的代码主要基于here的MSDN示例.
最佳答案 你缺少Native.loadLibrary的选项来告诉JNA自动映射到Process32FirstW(W32APIOptions.DEFAULT_OPTIONS会为你做这个).了解JNA本身如何加载kernel32库.
由于定义了使用Java char作为文件名的PROCESSENTRY32结构,因此JNA的platform.jar中包含的Process32First的定义实际上仅适用于unicode(-W)版本.你得到垃圾的原因是“ANSI”版本的编码字节数组已被读入Java char数组. Native.toString()试图从该数组中读取,不知道数据最初是编码的字节.