【问题标题】:How do I read the contents from an open Windows Console (Command Prompt) using Java Native Access如何使用 Java Native Access 从打开的 Windows 控制台(命令提示符)读取内容
【发布时间】:2019-10-06 00:33:46
【问题描述】:

我想阅读命令提示符窗口的文本内容。假设我打开了一个命令提示符,然后运行了 dir 命令,然后运行了 pwd 命令。所以问题陈述是,命令提示符中存在的任何内容我都应该能够阅读它们。我正在尝试使用 Java Native Access 库来实现这一点,但没有得到任何运气。我试过以下代码。但我没有得到任何输出。

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);
    }
}

不过,我可以使用下面的方法阅读记事本的文本。但是对于命令提示符,事情不起作用。请帮我解决这个问题。

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));
    }

【问题讨论】:

    标签: java command-prompt jna windows-console


    【解决方案1】:

    this one 等其他 StackOverflow 答案的简要调查表明,并非所有应用程序都响应 SendMessage() 函数,Windows 控制台(命令提示符窗口)就是其中之一。虽然SendMessage 提供了标准功能,但当它不起作用时,您必须为您尝试从中读取文本的程序使用本机 API;在这种情况下,控制台。

    Windows 有一个完整的Console API,其中包括用于与控制台交互的numerous functions。一些控制台函数已经映射到 JNA 的 WinCon 类中,该类由 Kernel32 继承,包括将另一个 PID 的控制台链接到您的进程的 AttachConsole 方法、用于获取句柄的 GetConsoleWindow 以及当您使用 FreeConsole 时完成获取句柄,但要读取控制台的内容,您需要在自己的代码中扩展 Kernel32 接口以添加更多映射函数:

    public interface MyKernel32 extends Kernel32 {
        MyKernel32 INSTANCE = Native.load("kernel32", MyKernel32.class, W32APIOptions.DEFAULT_OPTIONS);
    
        // Mapped functions go here
    }
    

    对于这个答案来说,编写完整的解决方案有点多,但在您尝试实施此问题时,请随时更新您的问题。您需要映射以下函数:

    【讨论】:

    • 试过以下方法,WinDef.HWND GetConsoleWindow(); int GetConsoleOutputCP(); boolean AttachConsole(int dwProcessId);。没有取得任何成功。尝试了来自docs.microsoft.com/en-us/windows/console/… 的示例程序。但它给出了0xC0000005:访问冲突读取位置0x00000006。。我忘记了C大时间。我是不是做错了什么,请指导我,我卡住了,无法进步。
    • 根据the docs,“一个进程最多可以附加到一个控制台。如果调用进程已经附加到一个控制台,则返回的错误代码是ERROR_ACCESS_DENIED(5)。”看来您需要先调用 FreeConsole 才能从当前控制台分离。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-18
    • 1970-01-01
    • 2011-06-08
    • 2014-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多