64位计算机上的32位Java辅助功能

时间:2011-12-14 01:37:22

标签: c# java pinvoke accessibility

我有一个32位应用程序,它使用Java Accessibility(WindowsAccessBridge-32.dll,通过Java Access Bridge),并且在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)。

有人能说出这里可能出错的地方吗?

3 个答案:

答案 0 :(得分:4)

问题出现在AccessibilityContext的类型中:

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

我错误地映射为IntPtr的AccessibilityContext(上面的acParent)在使用“旧”WindowsAccessBridge.dll库(在x86下使用)时实际上是Int32,在使用WOW64时遇到Int64.AccessBridge-32.dll图书馆。

结果是,代码 在x86和WOW x64之间有所区别,并且必须为每个代码单独编译。我在x64版本中通过#defined'ing 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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

拨打' initializeAccessBridge'要求您拥有一个活动的Windows消息泵。 在< initializeAccessBridge'内,它(最终)创建一个隐藏的对话窗口(使用CreateDialog)。创建对话框后,它会执行带有注册消息的PostMessage。访问桥的JavaVM端响应此消息,并将另一条消息发回到创建的对话框(它似乎是您的应用程序和Java VM之间的“hello&#type”类型握手)。因此,如果您的应用程序没有活动消息泵,则应用程序永远不会收到来自JavaVM的返回消息。