How do I read the contents from an open Windows Console (Command Prompt) using Java Native Access

不想你离开。 提交于 2020-01-15 03:32:09

问题


I want to read the text contents of the command prompt window. Let's say, I opened a command prompt, then ran a dir command and then pwd command. So the problem statement is that, what ever is present in the command prompt I should be able to read them. I am trying to use Java Native Access library for achieving this, but didn't get any luck with it. I have tried following code. But I am not getting any output.

import com.sun.jna.Native;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.RECT;
import com.sun.jna.platform.win32.WinUser.WNDENUMPROC;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.platform.win32.WinDef.LPARAM;
import com.sun.jna.platform.win32.WinDef.WPARAM;

public class NativeExtractor {

    public static void main(String ar[]) throws InterruptedException {
        System.out.println(System.getProperty("sun.arch.data.model"));
        executeNativeCommands();
    }

    public static void executeNativeCommands(){
        User32 user32 = User32.INSTANCE;
        //HWND notePadHwnd = user32.FindWindowA("Notepad",null  );
        HWND consoleHwnd = user32.FindWindowA("ConsoleWindowClass",null  );
        HWND editHwnd = user32.FindWindowExA(consoleHwnd, null, null, null);
        byte[] lParamStr = new byte[512];
        LRESULT resultBool = user32.SendMessageA(editHwnd, User32.WM_GETTEXT, 512, lParamStr);

        System.out.println("The content of the file is : " + Native.toString(lParamStr));
    }

    interface User32 extends StdCallLibrary {
        User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
        int WM_SETTEXT = 0x000c;
        int WM_GETTEXT = 0x000D;
        int GetWindowTextA(HWND hWnd, byte[] lpString, int nMaxCount);
        boolean EnumWindows(WinUser.WNDENUMPROC lpEnumFunc, Pointer arg);
        HWND FindWindowA(String lpClassName, String lpWindowName);
        HWND FindWindowExA(HWND hwndParent, HWND hwndChildAfter, String lpClassName, String lpWindowName);
        LRESULT SendMessageA(HWND paramHWND, int paramInt, WPARAM paramWPARAM, LPARAM paramLPARAM);
        LRESULT SendMessageA(HWND editHwnd, int wmGettext, long l, byte[] lParamStr);
        int GetClassNameA(HWND hWnd, byte[] lpString, int maxCount);

        void EnumChildWindows(HWND hwnd, WNDENUMPROC microsoft_word_document, Object o);
    }
}

Nevertheless, I can read the text of the notepad using below. But things are not working for command prompt . Please help me in resolving this .

public static void executeNativeCommands(){
        User32 user32 = User32.INSTANCE;
        HWND notePadHwnd = user32.FindWindowA("Notepad",null  );
        HWND editHwnd = user32.FindWindowExA(notePadHwnd, null, null, null);
        byte[] lParamStr = new byte[512];
        LRESULT resultBool = user32.SendMessageA(editHwnd, User32.WM_GETTEXT, 512, lParamStr);

        System.out.println("The content of the file is : " + Native.toString(lParamStr));
    }

回答1:


A brief survey of other StackOverflow answers like this one indicate that not all applications respond to the SendMessage() function, and the Windows Console (Command Prompt window) is one of those. While SendMessage provides a standard functionality, when it doesn't work you must use the Native API for the program you're trying to read text from; in this case, the Console.

Windows has a complete Console API that includes numerous functions for interacting with the console. Some console functions are already mapped in JNA's WinCon class which is inherited by Kernel32, including the AttachConsole method to link another PID's console to your process, GetConsoleWindow to obtain the handle, and FreeConsole when you are done fetching the handle, but to read the contents of the console you'll need to extend the Kernel32 interface in your own code in order to add more mapped functions:

public interface MyKernel32 extends Kernel32 {
    MyKernel32 INSTANCE = Native.load("kernel32", MyKernel32.class, W32APIOptions.DEFAULT_OPTIONS);

    // Mapped functions go here
}

Writing the full solution is a bit much for this answer, but feel free to update your question as you attempt to implement this. You'll need to map the following functions:

  • GetConsoleScreenBufferInfoEx (Vista+) or GetConsoleScreenBufferInfo (Win2K+) to get the console's buffer coordinates (rows and columns) to know how far back you can read
  • ReadConsoleOutput to actually copy the contents of the console buffer into your own buffer of characters to manipulate


来源:https://stackoverflow.com/questions/58026937/how-do-i-read-the-contents-from-an-open-windows-console-command-prompt-using-j

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!