diff --git a/src/org/synthuse/Api.java b/src/org/synthuse/Api.java index 469ddb8..4ab1a96 100644 --- a/src/org/synthuse/Api.java +++ b/src/org/synthuse/Api.java @@ -147,6 +147,8 @@ public class Api { int GetClassName(HWND hWnd, char[] buffer2, int i); int GetWindowModuleFileName(HWND hWnd, char[] buffer2, int i); int GetWindowThreadProcessId(HWND hWnd, PointerByReference pref); + //int GetWindowThreadProcessId(HWND hWnd, IntByReference lpdwProcessId); + boolean GetCursorPos(long[] lpPoint); //use macros POINT_X() and POINT_Y() on long lpPoint[0] diff --git a/src/org/synthuse/SynthuseDlg.java b/src/org/synthuse/SynthuseDlg.java index e5fa76f..674bd87 100644 --- a/src/org/synthuse/SynthuseDlg.java +++ b/src/org/synthuse/SynthuseDlg.java @@ -163,7 +163,6 @@ public class SynthuseDlg extends JFrame { btnRefresh = new JButton(" Refresh "); btnRefresh.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { - //lblStatus.setText("Loading Windows Enumerated Xml..."); //WindowsEnumeratedXml wex = new WindowsEnumeratedXml(textPane, lblStatus); //wex.run(); WindowsEnumeratedXml.getXmlThreaded(textPane, lblStatus); @@ -199,7 +198,20 @@ public class SynthuseDlg extends JFrame { helpBtn.setIcon(new ImageIcon(SynthuseDlg.class.getResource(RES_STR_HELP_IMG))); helpBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { - JOptionPane.showMessageDialog(null, "Version " + VERSION_STR + " create by Edward Jakubowski ejakubowski7@gmail.com", "About", JOptionPane.QUESTION_MESSAGE); + String about = ""; + about += "Synthuse Version " + VERSION_STR + " create by Edward Jakubowski ejakubowski7@gmail.com\n\n"; + + about += "System information: \n"; + about += " Java version - " + System.getProperty("java.version") + "\n"; + about += " Java home - " + System.getProperty("java.home") + "\n"; + about += " OS Name - " + System.getProperty("os.name") + "\n"; + about += " OS Arch - " + System.getProperty("os.arch") + "\n"; + String jclasspath = System.getProperty("java.class.path"); + jclasspath = jclasspath.replaceAll(";", ";\n "); + if (!System.getProperty("os.name").startsWith("Windows")) + jclasspath = jclasspath.replaceAll(":", ":\n "); + about += " Java class path - " + jclasspath + "\n\n"; + JOptionPane.showMessageDialog(null, about , "About", JOptionPane.QUESTION_MESSAGE); } }); toolBar.add(helpBtn); diff --git a/src/org/synthuse/WindowInfo.java b/src/org/synthuse/WindowInfo.java index 53d2861..08169bf 100644 --- a/src/org/synthuse/WindowInfo.java +++ b/src/org/synthuse/WindowInfo.java @@ -56,15 +56,14 @@ public class WindowInfo { parentStr = Api.GetHandleAsString(parent); } else { - //User32.instance.GetWindowModuleFileName(hWnd, path, 512); + PointerByReference pointer = new PointerByReference(); User32.instance.GetWindowThreadProcessId(hWnd, pointer); - Pointer p = pointer.getPointer(); - pid = p.getLong(0); + pid = pointer.getPointer().getInt(0); Pointer process = Kernel32.instance.OpenProcess(Api.PROCESS_QUERY_INFORMATION | Api.PROCESS_VM_READ, false, pointer.getValue()); Psapi.instance.GetModuleBaseNameW(process, null, buffer2, 512); processName = Native.toString(buffer2); - //processName = Native.toString(path); + } this.hwnd = hWnd; hwndStr = Api.GetHandleAsString(hWnd); diff --git a/src/org/synthuse/test/WinApiTest.java b/src/org/synthuse/test/WinApiTest.java new file mode 100644 index 0000000..6b0d7d2 --- /dev/null +++ b/src/org/synthuse/test/WinApiTest.java @@ -0,0 +1,138 @@ +package org.synthuse.test; + + +import java.util.LinkedHashMap; +import java.util.Map; + + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import static org.junit.Assert.*; + +import org.synthuse.Api; +import org.synthuse.WindowInfo; +import org.synthuse.WindowsEnumeratedXml; +import org.synthuse.Api.Kernel32; +import org.synthuse.Api.Psapi; +import org.synthuse.Api.User32; + +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.platform.win32.WinUser; +import com.sun.jna.platform.win32.WinDef.HWND; +import com.sun.jna.platform.win32.WinDef.RECT; +import com.sun.jna.ptr.PointerByReference; + +public class WinApiTest { + + @Before + public void setUp() throws Exception { + + } + + @After + public void tearDown() throws Exception { + + } + + public static void output(String val) { + System.out.println(val); + } + + //copied and modified slightly from WindowInfo class + public String getWindow32Information(HWND hWnd, boolean isChild) { + String hwndStr = ""; + HWND parent = null; + String parentStr = ""; + RECT rect; + String text; + String className = ""; + String processName = ""; + long pid = 0; + + byte[] buffer = new byte[1024]; + output("Calling GetWindowTextA"); + User32.instance.GetWindowTextA(hWnd, buffer, buffer.length); + text = Native.toString(buffer); + output("GetWindowTextA returned: " + text); + if (text.isEmpty()) { + output("Calling sendWmGetText"); + text = new Api().sendWmGetText(hWnd); + output("sendWmGetText returned: " + text); + } + + char[] buffer2 = new char[1026]; + output("Calling GetClassName"); + User32.instance.GetClassName(hWnd, buffer2, 1026); + className = Native.toString(buffer2); + output("GetClassName returned: " + className); + + rect = new RECT(); + output("Calling GetWindowRect"); + User32.instance.GetWindowRect(hWnd, rect); + output("GetWindowRect returned: " + rect.toString()); + + if (isChild) { + output("Calling GetParent"); + parent = User32.instance.GetParent(hWnd); + parentStr = Api.GetHandleAsString(parent); + output("GetParent returned: " + parentStr); + } + else { + //User32.instance.GetWindowModuleFileName(hWnd, path, 512); + //IntByReference pointer = new IntByReference(); + PointerByReference pointer = new PointerByReference(); + output("Calling GetWindowThreadProcessId"); + User32.instance.GetWindowThreadProcessId(hWnd, pointer); + pid = pointer.getPointer().getInt(0); + output("GetWindowThreadProcessId returned: " + pid); + Pointer process = Kernel32.instance.OpenProcess(Api.PROCESS_QUERY_INFORMATION | Api.PROCESS_VM_READ, false, pointer.getPointer()); + //output("OpenProcess returned: " + process.getLong(0)); + output("Calling GetModuleBaseNameW"); + Psapi.instance.GetModuleBaseNameW(process, null, buffer2, 512); + processName = Native.toString(buffer2); + output("GetModuleBaseNameW returned: " + processName); + //processName = Native.toString(path); + } + hwndStr = Api.GetHandleAsString(hWnd); + output("GetHandleAsString returned: " + hwndStr); + return hwndStr; + } + + @Test + public void enumerateParentWindowsTest() { + final Map infoList = new LinkedHashMap(); + + class ParentWindowCallback implements WinUser.WNDENUMPROC { + @Override + public boolean callback(HWND hWnd, Pointer lParam) { + output("Getting window info " + Api.GetHandleAsString(hWnd)); + //WindowInfo wi = new WindowInfo(hWnd, false); + infoList.put(getWindow32Information(hWnd, false), null); + //Api.User32.instance.EnumChildWindows(hWnd, new ChildWindowCallback(), new Pointer(0)); + return true; + } + } + Api.User32.instance.EnumWindows(new ParentWindowCallback(), 0); + output("enumerateParentWindowsTest size: " + infoList.size()); + assertTrue(infoList.size() > 0); + } + + @Test + public void getXmlTest() { + String xml = WindowsEnumeratedXml.getXml(); + output("getXmlTest len: " + xml.length()); + assertTrue(xml.length() > 500); + } + + public static void main(String[] args) { + output("WinApiTest"); + WinApiTest wat = new WinApiTest(); + wat.enumerateParentWindowsTest(); + wat.getXmlTest(); + output("done."); + + } + +} diff --git a/src/org/synthuse/test/WinFormsMockTestApp.exe b/src/org/synthuse/test/WinFormsMockTestApp.exe new file mode 100644 index 0000000..64b76a9 Binary files /dev/null and b/src/org/synthuse/test/WinFormsMockTestApp.exe differ diff --git a/src/org/synthuse/test/WpfBridgeTest.java b/src/org/synthuse/test/WpfBridgeTest.java index f02f5d0..be15446 100644 --- a/src/org/synthuse/test/WpfBridgeTest.java +++ b/src/org/synthuse/test/WpfBridgeTest.java @@ -1,16 +1,48 @@ package org.synthuse.test; import static org.junit.Assert.*; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + import org.junit.After; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.synthuse.*; public class WpfBridgeTest { + static Process mockApp = null; + public static void RunMockWpfApp() { + String tempFilename = ExtractFileFromJar("/org/synthuse/test/WpfMockTestApp.exe"); + Runtime runtime = Runtime.getRuntime(); + try { + mockApp = runtime.exec(tempFilename); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @BeforeClass + public static void setUpBeforeClass() { + //this runs only once for this class + RunMockWpfApp(); + } + + @AfterClass + public static void tearDownAfterClass() { + //this runs only once for this class + if (mockApp != null) + mockApp.destroy(); + } + @Before public void setUp() throws Exception { - + } @After @@ -41,7 +73,7 @@ public class WpfBridgeTest { System.out.println("wpf unfiltered countChildrenWindows: " + wb.countChildrenWindows()); } - @Test + //@Test public void countDescendantsWin32() { WpfBridge wb = new WpfBridge(); wb.setFrameworkId("Win32");//We should find some Win32 windows, maybe not WPF @@ -54,7 +86,7 @@ public class WpfBridgeTest { assertTrue(ufwin32Cnt >= win32Cnt); } - @Test + //@Test public void countDescendantsWpf() { WpfBridge wb = new WpfBridge(); wb.setFrameworkId("WPF");// maybe not WPF @@ -72,6 +104,9 @@ public class WpfBridgeTest { wb.setFrameworkId("WPF"); WinPtr wp = new WinPtr(api.user32.FindWindow(null, "MainWindow"));//find WpfMockTestApp.exe long handle = Long.parseLong(wp.hWndStr); + if (handle == 0) + return; + System.out.println("calling getRuntimeIdFromHandle: " + handle); String rid = wb.getRuntimeIdFromHandle(handle); System.out.println(wp.hWndStr + " getRuntimeIdFromHandle: " + rid); assertTrue(rid != null); @@ -91,6 +126,8 @@ public class WpfBridgeTest { wb.setTouchableOnly(false); WinPtr wp = new WinPtr(api.user32.FindWindow(null, "MainWindow"));//find WpfMockTestApp.exe long handle = Long.parseLong(wp.hWndStr); + if (handle == 0) + return; String rid = wb.getRuntimeIdFromHandle(handle); System.out.println(wp.hWndStr + " getRuntimeIdFromHandle: " + rid); if (rid == null) @@ -101,4 +138,55 @@ public class WpfBridgeTest { for(String w : wInfo) System.out.println(w); } + + public static String ExtractFileFromJar(String path) { + // Obtain filename from path + String[] parts = path.split("/"); + String filename = (parts.length > 1) ? parts[parts.length - 1] : null; + // Split filename to prexif and suffix (extension) + String prefix = ""; + String suffix = null; + if (filename != null) { + parts = filename.split("\\.", 2); + prefix = parts[0]; + suffix = (parts.length > 1) ? "."+parts[parts.length - 1] : null; + } + File temp = null; + try { + // Prepare temporary file + temp = File.createTempFile(prefix, suffix); + temp.deleteOnExit(); + } catch(Exception e) { + e.printStackTrace(); + } + if (!temp.exists()) { //some reason the temp file wasn't create so abort + System.out.println("File " + temp.getAbsolutePath() + " does not exist."); + return null; + } + + // Prepare buffer for data copying + byte[] buffer = new byte[1024]; + int readBytes; + // Open and check input stream + InputStream is = WpfBridgeTest.class.getResourceAsStream(path); + if (is == null) { //check if valid + System.out.println("File " + path + " was not found inside JAR."); + return null; + } + // Open output stream and copy data between source file in JAR and the temporary file + OutputStream os = null; + try { + os = new FileOutputStream(temp); + while ((readBytes = is.read(buffer)) != -1) { + os.write(buffer, 0, readBytes); + } + os.close(); + is.close(); + } catch(Exception e) { + e.printStackTrace(); + } + return temp.getAbsolutePath(); + // Finally, load the library + //System.load(temp.getAbsolutePath()); + } } diff --git a/src/org/synthuse/test/WpfMockTestApp.exe b/src/org/synthuse/test/WpfMockTestApp.exe index 05b1150..c5f8e27 100644 Binary files a/src/org/synthuse/test/WpfMockTestApp.exe and b/src/org/synthuse/test/WpfMockTestApp.exe differ