64位机器上的32位Java可访问性

本文关键字:访问 Java 32位 机器 64位 | 更新日期: 2023-09-27 18:17:41

我有一个32位的应用程序,它使用Java可访问性(WindowsAccessBridge-32.dll,通过Java访问桥),并在32位机器上完美工作,但在x64机器上失败。

我相信我已经追踪到Windows_run:

之后的第一个调用之一
getAccessibleContextFromHWND(hwnd, out vmId, out context)

定义如下:

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WindowsAccessBridge-32.dll", CallingConvention = CallingConvention.Cdecl)]
public extern static bool getAccessibleContextFromHWND(IntPtr hwnd, out Int32 vmID, out IntPtr acParent);

这个调用在32位系统上工作得很好,返回True,填充vmId(带有一些5位数的值)和上下文——而在64位系统上,它返回True,填充'context',但是为vmId返回'0'。

如果我假设0是有效的(即使它是一个随机的5位数字,类似于32位系统上的指针),下一个调用仍然失败:

AccessibleContextInfo aci = new API.AccessibleContextInfo();
if (!getAccessibleContextInfo(vmId, context, ref aci))
  throw new Exception();

地点:

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WindowsAccessBridge-32.dll", CallingConvention = CallingConvention.Cdecl)]
public extern static bool getAccessibleContextInfo(Int32 vmID, IntPtr ac, ref AccessibleContextInfo info);

(我省略了AccessibleContextInfo结构体,但我可以在必要时提供它)。

我知道库正在工作,因为JavaMonkey和JavaFerret工作正确。此外,调用isJavaWindow工作,返回'true',或'false'视情况而变,我链接到正确的DLL (WindowsAccessBridge-32)。

谁能建议这里可能有什么问题?

64位机器上的32位Java可访问性

问题出现在accessbilitycontext:

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WindowsAccessBridge-32.dll", CallingConvention = CallingConvention.Cdecl)]
public extern static bool getAccessibleContextFromHWND(IntPtr hwnd, out Int32 vmID, out IntPtr acParent);

AccessibilityContext(上面的acParent),我错误地映射为IntPtr,实际上是使用"遗留"WindowsAccessBridge.dll库(在x86下使用)时的Int32,以及使用WOW64 WindowsAccessBridge-32.dll库时的Int64。

因此,结果是,代码在x86和WOW x64之间具有,并且必须分别对它们进行编译。为此,我在x64构建期间#define' WOW64,始终引用Int64方法,并在x86上使用"shim"方法:
#if WOW64 // using x64
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WindowsAccessBridge-32.dll", CallingConvention = CallingConvention.Cdecl)]
public extern static bool getAccessibleContextFromHWND(IntPtr hwnd, out Int32 vmID, out Int64 acParent);
#else // using x86
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("WindowsAccessBridge.dll", EntryPoint = "getAccessibleContextFromHWND", CallingConvention = CallingConvention.Cdecl)]
private extern static bool _getAccessibleContextFromHWND(IntPtr hwnd, out Int32 vmID, out Int32 acParent);
public static bool getAccessibleContextFromHWND(IntPtr hwnd, out Int32 vmID, out Int64 acParent)
{
  Int32 _acParent;
  bool retVal = _getAccessibleContextFromHWND(hwnd, out vmID, out _acParent);
  acParent = _acParent;
  return retVal;
}
#endif

如果您使用64位JVM和32位版本的Java Access bridge,它将无法正常工作。您需要最近发布的64位版本的访问桥接。看到http://blogs.oracle.com/korn/entry/java_access_bridge_v2_0有关在64位窗口下安装用于32位JRE的32位访问桥的32位副本的说明,请参阅http://www.travisroth.com/2009/07/03/java访问-桥-和- 64位windows/

调用'initializeAccessBridge'需要你有一个活动的窗口消息泵。在'initializeAccessBridge'内部,它(最终)创建一个隐藏的对话框窗口(使用CreateDialog)。一旦创建了对话框,它将使用已注册的消息执行PostMessage。访问桥接的JavaVM端响应此消息,并将另一条消息发送回已创建的对话框(它似乎是应用程序和java VM之间的"hello"类型握手)。因此,如果您的应用程序没有活动消息泵,则来自JavaVM的返回消息永远不会被您的应用程序接收。