Java JNA:PROCESSENTRY32.szExeFile在转换为Java字符串时返回“???? …”

我是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()试图从该数组中读取,不知道数据最初是编码的字节.

点赞