JNA Windows获取进程路径

时间:2014-06-07 20:08:45

标签: java jna

我在stackoverflow上找到了这个代码,解释了如何获取所有正在运行的进程 在Windows上,这得到名字和pid

Kernel32 kernel32 = (Kernel32) Native.loadLibrary(Kernel32.class, W32APIOptions.UNICODE_OPTIONS);
Tlhelp32.PROCESSENTRY32.ByReference processEntry = new Tlhelp32.PROCESSENTRY32.ByReference();

WinNT.HANDLE snapshot = kernel32.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPPROCESS, new WinDef.DWORD(0));
try {
    while (kernel32.Process32Next(snapshot, processEntry)) {
        System.out.println(processEntry.th32ProcessID + "\t" + Native.toString(processEntry.szExeFile));
    }
} finally {
    kernel32.CloseHandle(snapshot);
}

我的问题是:我如何获得流程路径?

1 个答案:

答案 0 :(得分:3)

使用JNA,您需要定义MODULEENTRY32结构并映射一些必需的函数:

import java.util.Arrays;
import java.util.List;

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.win32.W32APIOptions;

public interface ProcessPathKernel32 extends Kernel32 {
    class MODULEENTRY32 extends Structure {
        public static class ByReference extends MODULEENTRY32 implements Structure.ByReference {
            public ByReference() {
            }

            public ByReference(Pointer memory) {
                super(memory);
            }
        }
        public MODULEENTRY32() {
            dwSize = new WinDef.DWORD(size());
        }

        public MODULEENTRY32(Pointer memory) {
            super(memory);
            read();
        }


        public DWORD dwSize;
        public DWORD th32ModuleID;
        public DWORD th32ProcessID;
        public DWORD GlblcntUsage;
        public DWORD ProccntUsage;
        public Pointer modBaseAddr;
        public DWORD modBaseSize;
        public HMODULE hModule;
        public char[] szModule = new char[255+1]; // MAX_MODULE_NAME32
        public char[] szExePath = new char[MAX_PATH];
        public String szModule() { return Native.toString(this.szModule); }
        public String szExePath() { return Native.toString(this.szExePath); }
        @Override
        protected List<String> getFieldOrder() {
            return Arrays.asList(new String[] {
                "dwSize", "th32ModuleID", "th32ProcessID", "GlblcntUsage", "ProccntUsage", "modBaseAddr", "modBaseSize", "hModule", "szModule", "szExePath"
            });
        }
    }

    ProcessPathKernel32 INSTANCE = (ProcessPathKernel32)Native.loadLibrary(ProcessPathKernel32.class, W32APIOptions.UNICODE_OPTIONS);
    boolean Module32First(HANDLE hSnapshot, MODULEENTRY32.ByReference lpme);
    boolean Module32Next(HANDLE hSnapshot, MODULEENTRY32.ByReference lpme);
}

然后检索进程并为每个PID检索模块信息(模块的路径现在可用)。如果从32位进程运行,那么您只能从32位进程获取模块信息(64位进程的路径将为空白)。

import com.sun.jna.Native;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.Kernel32Util;
import com.sun.jna.platform.win32.Tlhelp32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.win32.W32APIOptions;

public class ProcessPathAll {

    public static void main(String ... args) {
        Kernel32 kernel32 = (Kernel32) Native.loadLibrary(Kernel32.class, W32APIOptions.DEFAULT_OPTIONS);
        Tlhelp32.PROCESSENTRY32.ByReference processEntry = new Tlhelp32.PROCESSENTRY32.ByReference();
        WinNT.HANDLE processSnapshot = 
                kernel32.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPPROCESS, new WinDef.DWORD(0));
        try {

            while (kernel32.Process32Next(processSnapshot, processEntry)) {
                // looks for a specific process
                // if (Native.toString(processEntry.szExeFile).equalsIgnoreCase("textpad.exe")) {
                System.out.print(processEntry.th32ProcessID + "\t" + Native.toString(processEntry.szExeFile) + "\t");
                WinNT.HANDLE moduleSnapshot = 
                    kernel32.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPMODULE, processEntry.th32ProcessID);
                try {
                     ProcessPathKernel32.MODULEENTRY32.ByReference me = new ProcessPathKernel32.MODULEENTRY32.ByReference();
                     ProcessPathKernel32.INSTANCE.Module32First(moduleSnapshot, me);
                     System.out.print(": " + me.szExePath() );
                     System.out.println();
                 }
                 finally {
                     kernel32.CloseHandle(moduleSnapshot);
                 }
                // }
            }
        } 
        finally {
            kernel32.CloseHandle(processSnapshot);
        }
    }
}