0

我尝试使用WindowsAccessBridge.dll.

我可以获得窗口句柄,但调用函数isJavaWindow(System.IntPtr hWnd)总是返回false

请在下面找到我的代码:

    static void Main()
    {
        System.Int32 vmID = 0;
        System.Int64 _acParent = 0;
        string WndName = "GLOBUS EDU";
        string ClassName = "SunAwtFrame";

        Windows_run();
        System.IntPtr hWnd = System.IntPtr.Zero;
        hWnd = (System.IntPtr)FindWindow(ClassName, WndName);
        bool Found = isJavaWindow(hWnd);

        if (!Found) { throw new System.Exception("ERROR: Unable to find window by classname " + ClassName + " and " + WndName + "!"); }

        System.Console.WriteLine("Application is finished. Press ENTER to exit...");
        System.Console.ReadKey();
    }

互操作:

    [return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
    [System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]
    private extern static bool getAccessibleContextFromHWNDFct(System.IntPtr hwnd, out System.Int32 vmID, out System.Int32 _acParent);
    private static bool getAccesibleContextFromHWND(System.IntPtr hWnd, out System.Int32 vmID, out System.Int64 acParent)
    {
        System.Int32 ac = -1;
        bool retVal = false;

        getAccessibleContextFromHWNDFct(hWnd, out vmID, out ac);
        acParent = ac;

        return retVal;
    }

    [System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]
    private extern static bool getAccessibleContextInfo(int vmID, System.IntPtr ac, out AccessibleContextInfo textInfo);

    [System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl, ThrowOnUnmappableChar = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
    private extern static void Windows_run();

    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    private static extern System.IntPtr FindWindow(string lpClassName, string lpWindowName);

    [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
    private static extern System.IntPtr FindWindowByCaptionFct(System.IntPtr ZeroOnly, string lpWindowName);
    private static System.IntPtr FindWindowByCaption(string WindowTitle) { return FindWindowByCaptionFct(System.IntPtr.Zero, WindowTitle); }

    [System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl, ThrowOnUnmappableChar = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
    private extern static System.Boolean isJavaWindow(System.IntPtr hwnd);

该功能FindWindow运行完美,我也得到了 Spy++ 向我展示的窗口句柄。类名SunAwtFrame正如 Spy++ 所说。

我的 Java 应用程序以 64 位运行,但我尝试了所有库(-32、-64),并且还在 VS 配置管理器中从 x86 切换到 x64 并返回。

AccessBridge 本身运行良好——Java-Monkey-64.exe 可以监视我正在运行的 Java 应用程序。

有谁知道,为什么这不起作用?

问候,扬

4

2 回答 2

1

几天来我一直在与您的问题作斗争。

我创建了一个程序来枚举作为 java 应用程序的窗口(当然写在控制台应用程序上),并捕获像你一样的问题。然后,我在WPF应用程序上重写它,枚举所有窗口,然后认识到:除了普通窗口之外,我看到一个名为“java access bridge”的奇怪窗口,问题很明显:

Windows_run 函数需要有一个活动的 Windows 消息泵。 另一种方式,你必须把它放在 WPF 应用程序的构造函数或类似的东西上。

if (result != FALSE) {
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        shutdownAccessBridge();
    }

Java Monkey 应用程序中的代码。

创建隐藏窗口后,它会执行带有注册消息的 PostMessage。访问桥的 JVM 端响应此消息,并将另一条消息回传到创建的窗口。因此,他们通过这种方式进行交流。等等,只有在消息泵可以处理消息之后才能调用 JAB 函数。这就是为什么 java 猴子需要为它的业务使用回调的原因。

于 2019-05-20T03:51:03.970 回答
0

为类名传递 null,如下面的代码所示:

IntPtr hWnd = FindWindow(null, "GLOBUS EDU"); //cast to IntPtr is redundant
bool Found = isJavaWindow(hWnd);

参考在Pinvoke文档中,它对我有用!

于 2021-05-18T11:39:13.643 回答