使用C#调用WindowsAccessBridge.dll自动化Java应用时isJavaWindow返回false
Hey Jan, let's troubleshoot why isJavaWindow() is returning false even though you've got the correct window handle from FindWindow(). Here are the most likely fixes to try:
1. Fix the Interop Marshaling for isJavaWindow()
The biggest culprit here is probably incorrect return value marshaling. The Windows Access Bridge's isJavaWindow() returns a JNI jboolean (a 1-byte unsigned value), but your current DllImport doesn't explicitly specify how to marshal this to a C# bool. By default, C# marshals bool as UnmanagedType.Bool (a 4-byte Windows BOOL), which can cause misinterpretation of the return value.
Update your isJavaWindow() interop definition to explicitly marshal the return value as a 1-byte type:
[return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.U1)] [System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)] private extern static bool isJavaWindow(System.IntPtr hwnd);
Also, the CharSet.Unicode and ThrowOnUnmappableChar flags aren't necessary here since this function doesn't handle string parameters, so removing them simplifies the definition.
2. Verify Your Access Bridge Initialization Flow
While you're calling Windows_run(), some versions of the Windows Access Bridge require you to first initialize the bridge with Windows_initAccessBridge() before interacting with any other functions. Add this initialization call right before Windows_run():
// Add this line before Windows_run() Windows_initAccessBridge(); Windows_run();
You'll need to add the interop definition for this function too:
[System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)] private extern static void Windows_initAccessBridge();
3. Check if You're Targeting the Correct Window Hierarchy
Sometimes, the top-level SunAwtFrame window isn't the direct Java-accessible window—you might need to check its child windows. Try enumerating child windows of your hWnd and calling isJavaWindow() on each one to find the correct handle.
You can use EnumChildWindows from user32.dll to do this:
[System.Runtime.InteropServices.DllImport("user32.dll")] private static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam); private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); // Then use it like this: EnumChildWindows(hWnd, (childHwnd, param) => { if (isJavaWindow(childHwnd)) { Console.WriteLine($"Found Java child window: {childHwnd}"); // You can store this handle if needed return false; // Stop enumeration } return true; }, IntPtr.Zero);
4. Bypass isJavaWindow() and Test getAccessibleContextFromHWNDFct() Directly
If isJavaWindow() still misbehaves, try calling getAccessibleContextFromHWNDFct() directly. If this function returns true, it confirms the window is a Java window, and you can proceed with your automation without relying on isJavaWindow().
Fix your getAccesibleContextFromHWND() function first—it currently hardcodes retVal = false, which is a bug:
private static bool getAccesibleContextFromHWND(System.IntPtr hWnd, out System.Int32 vmID, out System.Int64 acParent) { System.Int32 ac = -1; bool retVal = getAccessibleContextFromHWNDFct(hWnd, out vmID, out ac); // Assign the actual return value here acParent = ac; return retVal; }
Then call it right after getting your window handle:
if (getAccesibleContextFromHWND(hWnd, out vmID, out _acParent)) { Console.WriteLine("Confirmed Java window via getAccessibleContextFromHWNDFct!"); } else { throw new System.Exception("ERROR: Unable to get accessible context for the window!"); }
5. Double-Check Platform Alignment
Even though you've switched between x86/x64, make sure:
- Your C# project's platform target matches the Java app (64-bit)
- You're referencing the correct
WindowsAccessBridge-64.dll(not accidentally using the 32-bit one) - The Java app is running with the Access Bridge enabled (since Java Monkey works, this is probably okay, but you can verify by checking
accessibility.propertiesin your JRE'slibfolder)
Give these steps a try—most likely the marshaling fix will resolve the isJavaWindow() issue.
内容的提问来源于stack exchange,提问作者Jan021981

