From f0b6b129bd1dce68fad725469e5f9e11ab6edf85 Mon Sep 17 00:00:00 2001 From: Michael Freeman Date: Sat, 31 Oct 2015 12:15:45 -0400 Subject: [PATCH 1/2] test for issue #520 --- .../COM/ShellApplicationWindowsTest.java | 232 ++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100644 contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java new file mode 100644 index 0000000000..c2b2947cf8 --- /dev/null +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java @@ -0,0 +1,232 @@ +package com.sun.jna.platform.win32.COM; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.sun.jna.Native; +import com.sun.jna.NativeLibrary; +import com.sun.jna.platform.win32.OleAuto; +import com.sun.jna.platform.win32.Variant; +import com.sun.jna.platform.win32.Variant.VARIANT; +import com.sun.jna.platform.win32.WinDef.LONG; +import com.sun.jna.platform.win32.WinDef.LONGLONG; + +import junit.framework.TestCase; + +public class ShellApplicationWindowsTest extends TestCase { + + @Override + protected void setUp() throws Exception { + String[] commands = {"cmd", "/c", "start", "iexplore.exe","-nohome", "\"http://www.srh.noaa.gov/jax\""}; + Runtime.getRuntime().exec(commands); + Thread.sleep(30000); + } + + public void testWindowsCount() { + System.out.println("java.vendor: " + System.getProperty("java.vendor")); + System.out.println("java.version: " + System.getProperty("java.version")); + System.out.println("os.version: " + System.getProperty("os.version")); + System.out.println("os.arch: " + System.getProperty("os.arch")); + System.out.println("os.name: " + System.getProperty("os.name")); + + ShellApplication sa = new ShellApplication(); + System.out.println("Shell.Application.Windows found: " + sa.Windows().Count()); + assertTrue(sa.Windows().Count() > 0); + for (InternetExplorer ie : sa.Windows()) + { + System.out.println(); + System.out.println("============================================"); + if (ie != null) + { + System.out.println("Title: " + ie.getTitle()); + System.out.println("URL: " + ie.getURL()); + System.out.println("App Name: " + ie.getName()); + System.out.println("Window Handle: " + ie.getWindowHandle()); + } + else + { + System.out.println("Null encountered."); + } + System.out.println("============================================"); + System.out.println(); + } + } + + @Override + protected void tearDown() throws Exception { + Runtime.getRuntime().exec("taskkill.exe /f /im iexplore.exe"); + } + + + + /** + * A COM representation of the Windows shell. + */ + private static class ShellApplication extends COMLateBindingObject + { + public ShellApplication() throws COMException + { + super("Shell.Application", false); + } + + /** + * @return Creates and returns a ShellWindows object.
+ * This object represents a collection of all of the open windows that belong to the Shell. + */ + public ShellWindows Windows() + { + return new ShellWindows((IDispatch) invoke("Windows").getValue()); + } + + /** + * Represents a collection of the open windows that belong to the Shell.
+ * Methods associated with this objects can control and execute commands within the Shell, and obtain other Shell-related objects. + */ + public static class ShellWindows extends COMLateBindingObject implements Iterable + { + + private static class ShellWindowsIterator implements Iterator + { + + private ShellWindows source; + + private int count; + + private int max; + + public ShellWindowsIterator(ShellWindows collection) + { + source = collection; + max = source.Count(); + } + + @Override + public boolean hasNext() + { + return count < max; + } + + @Override + public InternetExplorer next() + { + if (!hasNext()) + { + throw new NoSuchElementException(); + } + return source.Item(count++); + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } + + } + + public ShellWindows(IDispatch iDispatch) + { + super(iDispatch); + } + + /** + * Retrieves an InternetExplorer object that represents the Shell window. + * + * @param idx + * The zero-based index of the item to retrieve.
+ * This value must be less than the value of the Count property. + * @return an InternetExplorer object that represents the Shell window. + */ + public InternetExplorer Item(int idx) + { + VARIANT arg = new VARIANT(); + arg.setValue(Variant.VT_I4, new LONG(idx)); + IDispatch result = (IDispatch) invoke("Item", arg).getValue(); + if (result == null) + { + return null; + } + return new InternetExplorer(result); + } + + /** + * @return the number of items in the collection. + */ + public int Count() + { + return getIntProperty("Count"); + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override + public Iterator iterator() + { + return new ShellWindowsIterator(this); + } + } + + } + + /** + * InternetExplorer / IWebBrowser2 - see http://msdn.microsoft.com/en-us/library/aa752127(v=vs.85).aspx + */ + private static class InternetExplorer extends COMLateBindingObject + { + + public InternetExplorer(IDispatch iDispatch) + { + super(iDispatch); + } + + /** + * @return the title of the browser window. This may not always be the title of the main document + */ + public String getTitle() + { + return getStringProperty("LocationName"); + } + + /** + * IWebBrowser2::get_LocationURL
+ * Read-only COM property.
+ * + * @return the URL of the resource that is currently displayed. + */ + public String getURL() + { + return getStringProperty("LocationURL"); + } + + /** + * IWebBrowser2::get_Name
+ * Read-only COM property.
+ * + * @return the frame name or application name of the object. + */ + public String getName() + { + return getStringProperty("Name"); + } + + /** + * IWebBrowser2::HWND
+ * Read-only COM property.
+ * + * @return the handle of the Internet Explorer main window. + */ + public long getWindowHandle() + { + VARIANT.ByReference result = new VARIANT.ByReference(); + this.oleMethod(OleAuto.DISPATCH_PROPERTYGET, result, this.getIDispatch(), "HWND"); + + if (result.getVarType().intValue() == Variant.VT_I8) + { + return ((LONGLONG) result.getValue()).longValue(); + } + return ((LONG) result.getValue()).longValue(); + + } + } + + +} From 84041b3fb88b9eb22db23550a65d4f297d9507ba Mon Sep 17 00:00:00 2001 From: Michael Freeman Date: Sat, 31 Oct 2015 22:59:09 -0400 Subject: [PATCH 2/2] updating test to remove println()s and add more assertions --- .../COM/ShellApplicationWindowsTest.java | 128 ++++++------------ 1 file changed, 41 insertions(+), 87 deletions(-) diff --git a/contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java b/contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java index c2b2947cf8..1d0bd8687f 100644 --- a/contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java +++ b/contrib/platform/test/com/sun/jna/platform/win32/COM/ShellApplicationWindowsTest.java @@ -3,67 +3,60 @@ import java.util.Iterator; import java.util.NoSuchElementException; -import com.sun.jna.Native; -import com.sun.jna.NativeLibrary; -import com.sun.jna.platform.win32.OleAuto; import com.sun.jna.platform.win32.Variant; import com.sun.jna.platform.win32.Variant.VARIANT; import com.sun.jna.platform.win32.WinDef.LONG; -import com.sun.jna.platform.win32.WinDef.LONGLONG; import junit.framework.TestCase; -public class ShellApplicationWindowsTest extends TestCase { - - @Override - protected void setUp() throws Exception { - String[] commands = {"cmd", "/c", "start", "iexplore.exe","-nohome", "\"http://www.srh.noaa.gov/jax\""}; - Runtime.getRuntime().exec(commands); - Thread.sleep(30000); - } - - public void testWindowsCount() { - System.out.println("java.vendor: " + System.getProperty("java.vendor")); - System.out.println("java.version: " + System.getProperty("java.version")); - System.out.println("os.version: " + System.getProperty("os.version")); - System.out.println("os.arch: " + System.getProperty("os.arch")); - System.out.println("os.name: " + System.getProperty("os.name")); +public class ShellApplicationWindowsTest extends TestCase +{ + + @Override + public void setUp() throws Exception + { + // Launch IE in a manner that should ensure it opens even if the system default browser is Chrome, Firefox, or something else. + Runtime.getRuntime().exec("cmd /c start iexplore.exe -nohome \"about:blank\""); + // Even when going to "about:blank", IE still needs a few seconds to start up and add itself to Shell.Application.Windows + // Removing this delay will cause the test to fail even on the fastest boxes I can find. + Thread.sleep(3000); + } + + public void testWindowsCount() + { ShellApplication sa = new ShellApplication(); - System.out.println("Shell.Application.Windows found: " + sa.Windows().Count()); + + // IE is open, so there should be at least one present. + // More may exist if Windows Explorer windows are open. assertTrue(sa.Windows().Count() > 0); + + boolean pageFound = false; for (InternetExplorer ie : sa.Windows()) - { - System.out.println(); - System.out.println("============================================"); - if (ie != null) - { - System.out.println("Title: " + ie.getTitle()); - System.out.println("URL: " + ie.getURL()); - System.out.println("App Name: " + ie.getName()); - System.out.println("Window Handle: " + ie.getWindowHandle()); - } - else + { + // For reasons unknown, Shell.Application.Windows can have null members inside it. + // All I care about is whether or not the collection contains the window I opened. + if (ie != null && "about:blank".equals(ie.getURL())) { - System.out.println("Null encountered."); + pageFound = true; } - System.out.println("============================================"); - System.out.println(); } - } - - @Override - protected void tearDown() throws Exception { - Runtime.getRuntime().exec("taskkill.exe /f /im iexplore.exe"); - } - - - + + // Finally, did we find our page in the collection? + assertTrue(pageFound); + } + + @Override + protected void tearDown() throws Exception + { + Runtime.getRuntime().exec("taskkill.exe /f /im iexplore.exe"); + } + /** * A COM representation of the Windows shell. */ private static class ShellApplication extends COMLateBindingObject - { + { public ShellApplication() throws COMException { super("Shell.Application", false); @@ -89,11 +82,11 @@ private static class ShellWindowsIterator implements Iterator { private ShellWindows source; - + private int count; - + private int max; - + public ShellWindowsIterator(ShellWindows collection) { source = collection; @@ -178,14 +171,6 @@ public InternetExplorer(IDispatch iDispatch) super(iDispatch); } - /** - * @return the title of the browser window. This may not always be the title of the main document - */ - public String getTitle() - { - return getStringProperty("LocationName"); - } - /** * IWebBrowser2::get_LocationURL
* Read-only COM property.
@@ -196,37 +181,6 @@ public String getURL() { return getStringProperty("LocationURL"); } - - /** - * IWebBrowser2::get_Name
- * Read-only COM property.
- * - * @return the frame name or application name of the object. - */ - public String getName() - { - return getStringProperty("Name"); - } - - /** - * IWebBrowser2::HWND
- * Read-only COM property.
- * - * @return the handle of the Internet Explorer main window. - */ - public long getWindowHandle() - { - VARIANT.ByReference result = new VARIANT.ByReference(); - this.oleMethod(OleAuto.DISPATCH_PROPERTYGET, result, this.getIDispatch(), "HWND"); - - if (result.getVarType().intValue() == Variant.VT_I8) - { - return ((LONGLONG) result.getValue()).longValue(); - } - return ((LONG) result.getValue()).longValue(); - - } } - - + }