WindowsAccessBridge for Java Automation using C#

2k Views Asked by At

I try to automate an java application using WindowsAccessBridge.dll.

I can get the window handle but calling the function isJavaWindow(System.IntPtr hWnd) always return false

Please find my code below:

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

Interop:

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

The function FindWindowis working perfect and I'm getting the window handle also Spy++ shows me. The classname is SunAwtFrameas Spy++ says.

My Java applications runs in 64 bit but I tried all the Libraries (-32, -64) and also switched in the VS Configuration Manager from x86 to x64 and back.

The AccessBridge itself is working well - Java-Monkey-64.exe can spy my running java application.

Does anybody has an idea, why this is not working?

Regards, Jan

2

There are 2 best solutions below

0
On

Pass null for class name as in the below code:

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

Reference is here on Pinvoke documentation, and it works for me!

0
On

I have been fighting with your problem in few days.

i created a program that enumerate window that is java application(of course write on console application), and catch same problem like yours. then, i rewrite it on WPF application,enumerate all window, then recognize that: besides the normal window, i see a strange window named: "java access bridge", and the problem is clearly:

the Windows_run function need to have an active windows message pump. another way, you must putting it on the constructor of a WPF application or something same that.

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

code in Java Monkey application.

After create a hidden window, it performs a PostMessage with a registered message. The JVM side of the access bridge responds to this message, and posts back another message to the window that was created. As such, they communicate by that way. and more, you only can call JAB functions after the message pump can process messages. that is reason why the java monkey need to use call back for it's business.