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

Mel*_*var 5 c# java pinvoke accessibility

我有一个32位应用程序,它使用Java Accessibility(WindowsAccessBridge-32.dll,通过Java Access Bridge),并且在32位计算机上运行完美,但在x64计算机上失败.

我相信我已将其追踪到Windows_run之后的第一个电话:

getAccessibleContextFromHWND(hwnd, out vmId, out context)
Run Code Online (Sandbox Code Playgroud)

定义如下:

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

此调用在32位系统上正常工作,返回True,填充vmId(具有一些5位数值,其中)和上下文 - 而在64位系统上,它返回True,填充'context',但返回vmId为'0'.

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

AccessibleContextInfo aci = new API.AccessibleContextInfo();
if (!getAccessibleContextInfo(vmId, context, ref aci))
  throw new Exception();
Run Code Online (Sandbox Code Playgroud)

哪里:

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

(为简洁起见,我省略了AccessibleContextInfo结构,但如果需要,我可以提供它).

我知道库正在运行,因为JavaMonkey和JavaFerret都能正常工作.此外,调用isJavaWindow工作,适当地返回'true'或'false',并且我链接到正确的DLL(WindowsAccessBridge-32).

任何人都可以建议这里可能有什么问题?

Mel*_*var 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);
Run Code Online (Sandbox Code Playgroud)

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

所以结果是,x86 和 WOW x64 之间的代码必须有所不同,并且必须为每个代码单独编译。我通过在 x64 构建期间 #define'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
Run Code Online (Sandbox Code Playgroud)