This is my implementation that integrates the Java Access Bridge with a c# console application. Not the most elegant code but it gives a general idea.
- run the messaging pump.
- Use a timer to look for all running process and find a java application
- call Application.Run();
My main program
class Program
{
static void Main(string[] args)
{
ExecuteProcess();
}
static void ExecuteProcess()
{
string dllDirectory = Directory.GetCurrentDirectory();
Environment.SetEnvironmentVariable("PATH", Path.Combine(dllDirectory, "libs-ext"), EnvironmentVariableTarget.Process);
Environment.SetEnvironmentVariable("JAVA_ACCESSBRIDGE_LOGDIR", @"c:\accessbridgelog", EnvironmentVariableTarget.Process);
new AccessBridge();
Application.Run();
}
}
My AccessBridge Class:
class AccessBridge : IDisposable
{
private readonly JavaAccessBridgAPI bridgeWrapper;
private Thread messageLoopThread;
private object threadState = new object();
public AccessBridge()
{
bridgeWrapper = new JavaAccessBridgAPI();
RunMessagePump();
bridgeWrapper.InitializeBridge();
}
/// <summary>
/// Get running processes to find and check witch one is a Java program
/// </summary>
private void EnumerateWindows()
{
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
IntPtr hwnd = process.MainWindowHandle;
if (hwnd != IntPtr.Zero)
{
try
{
Console.WriteLine($"Process: {process.ProcessName} (ID: {process.Id}) - Main Window Handle: 0x{hwnd.ToInt32():X8}");
if (!bridgeWrapper.CheckIfJavaWindow(hwnd))
{
Console.WriteLine($"\n\t....Not a Java window.");
}
else
{
Console.WriteLine($"\n\t....IS A Java window :)");
}
}
catch (SEHException ex)
{
Console.Error.WriteLine($"{process.ProcessName} - Failed checking. {ex}");
}
catch (Exception ex)
{
Console.Error.WriteLine($"{process.ProcessName} - Failed checking. {ex}");
}
}
}
}
private Timer timer;
private void RunMessagePump()
{
// Start message loop
// Start message loop in a separate thread
messageLoopThread = new Thread(RunMessageLoop);
messageLoopThread.IsBackground = true; // Ensure it doesn't block program exit
messageLoopThread.Start();
timer = new Timer((state) => {
EnumerateWindows();
}, threadState, 5000, Timeout.Infinite );
}
private void RunMessageLoop()
{
MSG msg;
while (GetMessage(out msg, IntPtr.Zero, 0, 0))
{
TranslateMessage(ref msg);
DispatchMessage(ref msg);
}
// Optional: shutdownAccessBridge(); if needed
}
[StructLayout(LayoutKind.Sequential)]
public struct MSG
{
public IntPtr hwnd;
public uint message;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public Point pt;
public int lPrivate;
}
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
[DllImport("user32.dll")]
public static extern bool TranslateMessage([In] ref MSG lpMsg);
[DllImport("user32.dll")]
public static extern IntPtr DispatchMessage([In] ref MSG lpmsg);
public void Dispose()
{
timer?.Dispose();
}
}
My JavaAccessBridgAPI implementation:
public class JavaAccessBridgAPI
{
private const string DllName = "WindowsAccessBridge-64.dll";
[DllImport(DllName, CallingConvention = CallingConvention.Winapi, EntryPoint = "Windows_run")]
private static extern void Windows_run();
[DllImport(DllName, CallingConvention = CallingConvention.Winapi, EntryPoint = "isJavaWindow")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsJavaWindow(IntPtr hwnd);
[DllImport(DllName, CallingConvention = CallingConvention.Winapi, EntryPoint = "getAccessibleContextFromHWND")]
private static extern bool Windows_GetAccessibleContextFromHWND(IntPtr hwnd, out IntPtr ac);
[DllImport(DllName, CallingConvention = CallingConvention.Winapi, EntryPoint = "GetAccessibleName")]
private static extern bool Windows_GetAccessibleName(IntPtr ac, IntPtr nameBuffer, int bufferSize);
public bool InitializeBridge()
{
Windows_run();
return true;
}
public bool CheckIfJavaWindow(IntPtr hwnd) => IsJavaWindow(hwnd);
public bool RetrieveAccessibleContext(IntPtr hwnd, out IntPtr ac) => Windows_GetAccessibleContextFromHWND(hwnd, out ac);
public bool RetrieveAccessibleName(IntPtr ac, IntPtr nameBuffer, int bufferSize) => Windows_GetAccessibleName(ac, nameBuffer, bufferSize);
}
the windowsaccessbridge-64.dll must be in the same folder as the main program or in the "libs-ext"
Environment.SetEnvironmentVariable("PATH", Path.Combine(dllDirectory, "libs-ext"), EnvironmentVariableTarget.Process);