Jegan Kumar
Jegan Kumar

Reputation: 61

C# to automate Java application with Java Access Bridge

I have a Java application that I want to automate for testing. Unfortunately, the app window only registers as a SunAWTFrame, which means none of the controls are exposed to typical window analysis and automation tools.

My search has lead me to C# and utilising Java Access Bridge DLLS in a C# program to automate it.

Has anyone had any experience of this?

Oracle provides JavaAccessBridge (JAB) with some DLLS to help with this as I understand it after reading a few articles around the internet. There are some code examples but I'm really not groking it right now. By breaking it down, I think this is what needs to be achieved:

  1. Import / load / parse the JAB dlls
  2. Map functions in the JAB dll to methods / calls within my program
  3. Have the Java application to automate run (with JAB enabled) and get handle of it to my program
  4. Utilise the JAB functions to control the Java application

I don't know C# as well as I know Java, but that's not going to stop me.

If anyone can provide help, guidance, pointers or anything to get me started, that'd be truly awesome.

Upvotes: 6

Views: 4408

Answers (2)

Daniel Barnes
Daniel Barnes

Reputation: 397

Building on Stackia's great tip to use Google's AccessBridgeExplorer, Here are some tips to get you going:

  • Download Access Bridge Explorer

  • Use the WindowsAccessBridgeInterop.dll in your own (WinForms not Console) project (Add> Project Reference> Select the DLL)

  • Create a new access bridge object

    AccessBridge Java = new AccessBridge();

  • Initialize the Access Bridge object

    Java.Initialize();

  • Call Application.DoEvents() - A hack to wait for Java.Initialize to complete (My simple understanding is Java Access Bridge Uses a hidden window or similar)

    Application.DoEvents(); //this waits for Java Bridge to initilize ;)

  • Get the handle of the Java Window (plenty of examples online of how to get a Window Handle in C#)

  • Get Access to the Java Object that represents the window:

    Java.Functions.GetAccessibleContextFromHWND(Handle, out int vmid, out JavaObjectHandle javaObjectHandle);

  • Get AccessibleWindow Object for Window (so you can find its children)

    AccessibleWindow win = Java.CreateAccessibleWindow(handle);

  • Come up with your own way to cycle through the children, and the childrens children until you find the object you are after:

    //Similar to: foreach(var child in win.GetChildren()) JavaObjectHandle? javaObject = Java.Functions.GetAccessibleChildFromContext(node.JvmId, parentJavaObject, child.GetIndexInParent());

    //to get the label or title of the object:

    child.GetTitle();

  • To Interact with an object (eg click a button), do similar to the following: (please note where it says JavaObject - it means the child java object (eg. to click a button you need to get the JavaObject for that button using GetAccessibleChildFromContext as i mentioned above)

    //Get Possible Actions JavaAutomation.Java.Functions.GetAccessibleActions(VMID, JavaObject, out AccessibleActions accessibleActions);

              foreach( var action in accessibleActions.actionInfo)
              {
                  Log.Info($"DoAction: {action.name}");
              }
    
              AccessibleActionsToDo accessibleActionsToDo = new AccessibleActionsToDo();
              accessibleActionsToDo.actions = accessibleActions.actionInfo;
              accessibleActionsToDo.actionsCount = accessibleActions.actionsCount;
    
              //Do Actions
              JavaAutomation.Java.Functions.DoAccessibleActions(VMID, JavaObject, ref accessibleActionsToDo, out int failure);
    

Upvotes: 5

Stackia
Stackia

Reputation: 2151

As of 2019 we have a great tool AccessBridgeExplorer created and open-sourced by google. It's a really good staring point that contains a WindowsAccessBridgeInterop project which encapsulates almost every JAB API into a class oriented, .NET friendly assembly.

One notable thing, AccessBridge.Initialize() must be called in WPF/WinForm UI thread or in your own messaging pump thread, otherwise some methods like AccessBridge.EnumJvms() will always return false/empty.

Upvotes: 7

Related Questions