Search code examples
javawinapijna

How do I get the active window's application's name with JNA?


I have the following code using the JNA library which outputs the active window's title.

private static final int MAX_TITLE_LENGTH = 1024;

public static void main(String[] args) throws Exception {

    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
    LocalDateTime now = LocalDateTime.now();
    TimerTask task = new TimerTask() {
        @Override
        public void run() {
            char[] buffer = new char[MAX_TITLE_LENGTH * 2];
            HWND hwnd = User32.INSTANCE.GetForegroundWindow();
            User32.INSTANCE.GetWindowText(hwnd, buffer, MAX_TITLE_LENGTH);
            System.out.println("Active window title: " + Native.toString(buffer));
            try {
                BufferedWriter bw = new BufferedWriter(
                    new FileWriter(
                        new File("C:\\Users\\" + System.getProperty("user.name") + "\\AppData\\Roaming\\system\\useracivity.txt"),
                        true
                    )
                );
                bw.write(Native.toString(buffer) + " TIME WAS " + dtf.format(now));
                bw.newLine();
                bw.close();
            } catch (Exception e) {
            }
        }
    };

    Timer timer = new Timer();
    timer.schedule(task, new Date(), 5000);

}

But how do I get the name of the application, for example for Chrome "chrome.exe"?

Thanks in advance


Solution

  • I've found that GetWindowModuleFilename doesn't really work most of the time. QueryFullProcessImageName, however, works just fine. Note that you still do need to OpenProcess the process to access the image file name.

    Try this in a console application. It will print out the active window's image filename when you change the window.

    import com.sun.jna.platform.win32.*;
    import com.sun.jna.platform.win32.WinDef.HWND;
    import com.sun.jna.platform.win32.WinNT.HANDLE;
    import com.sun.jna.ptr.IntByReference;
    
    public class Main {
        public static void main(String[] args) throws Exception {
            HWND prevFg = null;
    
            while (true) {
                Thread.sleep(200);
    
                HWND fg = User32.INSTANCE.GetForegroundWindow();
    
                // don't print the name if it's still the same window as previously
                if (fg.equals(prevFg)) {
                    continue;
                }
    
                String fgImageName = getImageName(fg);
                if (fgImageName == null) {
                    System.out.println("Failed to get the image name!");
                } else {
                    System.out.println(fgImageName);
                }
    
                prevFg = fg;
            }
        }
    
        private static String getImageName(HWND window) {
            // Get the process ID of the window
            IntByReference procId = new IntByReference();
            User32.INSTANCE.GetWindowThreadProcessId(window, procId);
    
            // Open the process to get permissions to the image name
            HANDLE procHandle = Kernel32.INSTANCE.OpenProcess(
                    Kernel32.PROCESS_QUERY_LIMITED_INFORMATION,
                    false,
                    procId.getValue()
            );
    
            // Get the image name
            char[] buffer = new char[4096];
            IntByReference bufferSize = new IntByReference(buffer.length);
            boolean success = Kernel32.INSTANCE.QueryFullProcessImageName(procHandle, 0, buffer, bufferSize);
    
            // Clean up: close the opened process
            Kernel32.INSTANCE.CloseHandle(procHandle);
    
            return success ? new String(buffer, 0, bufferSize.getValue()) : null;
        }
    }
    

    Clicking around my windows, the program prints out lines like these:

    C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2017.3.5\bin\idea64.exe
    C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
    C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2017.3.5\bin\idea64.exe