java-access-bridge-wrapper
java-access-bridge-wrapper is a Python wrapper for the Windows Java Access Bridge (JAB). It enables Python applications to interact with and automate Java user interfaces on the Windows operating system. This library, currently at version 2.0.0, is primarily designed for 64-bit Windows environments and Java Development Kit (JDK) or Java Runtime Environment (JRE) versions 8 or higher.
Warnings
- breaking The library explicitly supports only 64-bit Windows operating systems. Using it with 32-bit Windows or 32-bit Java applications is not supported and will likely result in errors or unexpected behavior. Ensure your Java installation and target application are 64-bit.
- gotcha The Java Access Bridge must be explicitly enabled in your Windows environment for the wrapper to function. This is a one-time setup step for the Java installation you are targeting.
- gotcha The `JavaAccessBridgeWrapper` requires a Windows message pump to be running in the same thread as the JABWrapper object to properly process UI events and interact with Java applications. Failing to implement this will prevent the library from working correctly.
- gotcha The `WindowsAccessBridge-64.dll` path might need to be explicitly specified if Java is installed in a non-standard location or if the library cannot find it automatically. This can lead to initialization failures.
- gotcha Interacting with Java applications can sometimes be unstable. Common issues include target applications not supporting certain callbacks/actions, or crashes when highlighting/accessing elements, especially if a screen has a very large number of elements.
Install
-
pip install java-access-bridge-wrapper
Imports
- JavaAccessBridgeWrapper
from JABWrapper.jab_wrapper import JavaAccessBridgeWrapper
- ContextNode
from JABWrapper.context_tree import ContextNode
- ContextTree
from JABWrapper.context_tree import ContextTree
- SearchElement
from JABWrapper.context_tree import SearchElement
Quickstart
import ctypes
import queue
import threading
import time
from ctypes import wintypes, byref
from JABWrapper.jab_wrapper import JavaAccessBridgeWrapper
from JABWrapper.context_tree import ContextTree # Optional, for element interaction
def pump_background(pipe: queue.Queue):
"""Runs the Windows message pump in a background thread."""
try:
jab_wrapper = JavaAccessBridgeWrapper()
pipe.put(jab_wrapper)
message = byref(wintypes.MSG())
# The message pump is essential for JAB to receive events
while ctypes.windll.user32.GetMessageW(message, 0, 0, 0) > 0:
ctypes.windll.user32.TranslateMessage(message)
ctypes.windll.user32.DispatchMessageW(message)
except Exception as err:
pipe.put(None)
print(f"Error in message pump: {err}")
def main():
pipe = queue.Queue()
# Start the message pump in a separate thread
thread = threading.Thread(target=pump_background, daemon=True, args=[pipe])
thread.start()
# Retrieve the initialized JABWrapper object from the background thread
jab_wrapper = pipe.get()
if not jab_wrapper:
raise Exception("Failed to initialize Java Access Bridge Wrapper")
print("Java Access Bridge Wrapper initialized.")
# Give JAB a moment to process initial messages
time.sleep(0.5)
# Example: List available Java windows (requires a Java app running)
try:
windows = jab_wrapper.get_windows()
if windows:
print("\nDiscovered Java Windows:")
for i, window in enumerate(windows):
print(f" [{i+1}] Title: {window.title}, PID: {window.pid}")
# Example: Attach to the first Java window found (if any)
if len(windows) > 0:
first_window = windows[0]
print(f"\nAttempting to switch to: {first_window.title}")
jab_wrapper.switch_window_by_title(first_window.title)
print(f"Successfully switched to window: {jab_wrapper.get_main_frame_title()}")
# Optional: Get and print the context tree of the active window
print("\nBuilding context tree...")
context_tree = ContextTree(jab_wrapper)
# This can be very verbose, only print a few levels or specific elements
# For a full tree, consider pretty-printing or specific searches
# print(context_tree.get_tree_string())
print(f"Root element role: {context_tree.get_root().role}, name: {context_tree.get_root().name}")
else:
print("No Java windows found. Please ensure a Java application is running.")
except Exception as e:
print(f"An error occurred during interaction: {e}")
finally:
print("\nShutting down Java Access Bridge Wrapper.")
if jab_wrapper:
jab_wrapper.shutdown()
thread.join(timeout=1) # Give the thread a moment to finish cleanly
if __name__ == "__main__":
# Ensure Java Access Bridge is enabled and a Java application is running.
# For testing, you might need a simple Swing/AWT app.
main()