64 位计算机上的 32 位 Java 可访问性

发布于 2024-12-21 02:42:16 字数 1349 浏览 3 评论 0原文

我有一个使用 Java Accessibility(WindowsAccessBridge-32.dll,通过 Java Access Bridge)的 32 位应用程序,并且在 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,填充“上下文”,但为 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)。

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

I have a 32-bit app that makes use of Java Accessibility (WindowsAccessBridge-32.dll, via the Java Access Bridge), and works perfectly on a 32-bit machine, but fails on an x64 machine.

I believe I have tracked it down to one of the first calls after Windows_run:

getAccessibleContextFromHWND(hwnd, out vmId, out context)

defined as follows:

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

This call works fine on the 32-bit system, returning True, populating both vmId (with some 5-digit value, which), and context - whereas on the 64-bit system, it returns True, populates 'context', but returns '0' for vmId.

If I assume that 0 is valid (even though it's a random 5-digit number resembling a pointer on the 32-bit system), the next call still fails:

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

where:

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

(I'm omitting the AccessibleContextInfo struct for brevity, but I can provide it if necessary).

I know that the libraries are working, because both JavaMonkey and JavaFerret work correctly. Furthermore, call to isJavaWindow works, returning 'true', or 'false' as appropriate, and I am linking to the correct DLL (WindowsAccessBridge-32).

Can anyone suggest what may be wrong here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

半世蒼涼 2024-12-28 02:42:16

看来问题出在 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);

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

因此,结果是,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

It appears that the problem is in the type of 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);

AccessibilityContext (acParent above), which I had incorrectly mapped as an IntPtr, is actually an Int32 when using the "legacy" WindowsAccessBridge.dll library (used under x86), and an Int64 when using the WOW64 WindowsAccessBridge-32.dll library.

So the upshot is, the code has to differ between x86 and WOW x64, and must be compiled separately for each. I do this by #define'ing WOW64 during x64 builds, always referencing the Int64 methods, and using "shim" methods on x86:

#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
爱她像谁 2024-12-28 02:42:16

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

If your using a 64 bit JVM with a 32 bit version of the Java Access bridge it won't work correctly. You need a 64 bit version of the access bridge which has recently been released. see
http://blogs.oracle.com/korn/entry/java_access_bridge_v2_0
For instructions on installing a 32 bit copy of the access bridge for use with 32 bit JRE's under 64 bit windows see
http://www.travisroth.com/2009/07/03/java-access-bridge-and-64-bit-windows/

静水深流 2024-12-28 02:42:16

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

The call to 'initializeAccessBridge' REQUIRES you to have an active windows message pump.
Inside 'initializeAccessBridge', it (eventually) creates a hidden dialog window (using CreateDialog). Once the dialog is created, it performs a PostMessage with a registered message. The JavaVM side of the access bridge responds to this message, and posts back another message to the dialog that was created (it appears to be a 'hello' type handshake between your app and the java VM). As such, if your application doesn't have an active message pump, the return message from the JavaVM never gets received by your app.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文