diff --git a/src/modules/imageresizer/ui/App.xaml.cs b/src/modules/imageresizer/ui/App.xaml.cs index c2493148b1ca..91acf2a3223e 100644 --- a/src/modules/imageresizer/ui/App.xaml.cs +++ b/src/modules/imageresizer/ui/App.xaml.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. Code forked from Brice Lambson's https://github.com/bricelam/ImageResizer/ using System; +using System.Diagnostics; +using System.Runtime.InteropServices; using System.Text; using System.Windows; using GalaSoft.MvvmLight.Threading; @@ -16,6 +18,14 @@ namespace ImageResizer { public partial class App : Application { + // Import the FindWindow API to find our window + [DllImportAttribute("User32.dll")] + private static extern int FindWindow(string className, string windowName); + + // Import the SetForeground API to activate it + [DllImportAttribute("User32.dll")] + private static extern IntPtr SetForegroundWindow(int hWnd); + static App() { Console.InputEncoding = Encoding.Unicode; @@ -28,10 +38,32 @@ protected override void OnStartup(StartupEventArgs e) // TODO: Add command-line parameters that can be used in lieu of the input page (issue #14) var mainWindow = new MainWindow(new MainViewModel(batch, Settings.Default)); - mainWindow.Show(); - // Temporary workaround for issue #1273 - BecomeForegroundWindow(new System.Windows.Interop.WindowInteropHelper(mainWindow).Handle); + // Check process running + if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).GetUpperBound(0) == 0) + { + mainWindow.Show(); + + // Temporary workaround for issue #1273 + BecomeForegroundWindow(new System.Windows.Interop.WindowInteropHelper(mainWindow).Handle); + } + else + { + // The program has the open file dialog window and the image resizer window + // Find the window, using the Window title + // Check which window is running + int hWndOpen = FindWindow(null, "Image Resizer - Open files"); + int hWndImageResizer = FindWindow(null, "Image Resizer"); + if (hWndOpen > 0) + { + SetForegroundWindow(hWndOpen); // Activate Image Resizer - Open files window + } + + if (hWndImageResizer > 0) + { + SetForegroundWindow(hWndImageResizer); // Activate Image Resizer window + } + } } private void BecomeForegroundWindow(IntPtr hWnd) diff --git a/src/modules/imageresizer/ui/Views/MainWindow.xaml.cs b/src/modules/imageresizer/ui/Views/MainWindow.xaml.cs index 62d7c7721401..4b984cd1be28 100644 --- a/src/modules/imageresizer/ui/Views/MainWindow.xaml.cs +++ b/src/modules/imageresizer/ui/Views/MainWindow.xaml.cs @@ -29,6 +29,9 @@ public IEnumerable OpenPictureFiles() AppResources.AllFilesFilter + "|*.*", InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), Multiselect = true, + + // Create the Window title for OpenFileDialog + Title = "Image Resizer - Open files", }; if (openFileDialog.ShowDialog() != true) @@ -43,6 +46,15 @@ public void ShowAdvanced(AdvancedViewModel viewModel) => viewModel.Close(new AdvancedWindow(viewModel).ShowDialog() == true); void IMainView.Close() - => Dispatcher.Invoke((Action)Close); + { + Dispatcher.Invoke((Action)Close); + + // Close background processes when close the program + var processes = System.Diagnostics.Process.GetProcessesByName("ImageResizer"); + foreach (var process in processes) + { + process.Kill(); + } + } } } diff --git a/src/runner/resource.h b/src/runner/resource.h index 4c46fef4c9ca..c0c5343a0eaa 100644 --- a/src/runner/resource.h +++ b/src/runner/resource.h @@ -10,3 +10,6 @@ #define ID_EXIT_MENU_COMMAND 40001 #define ID_SETTINGS_MENU_COMMAND 40002 #define ID_ABOUT_MENU_COMMAND 40003 +#define ID_CHECK_FOR_UPDATES_COMMAND 40004 +#define ID_IMAGE_RESIZER_COMMAND 40005 +#define ID_WINDOW_WALKER_COMMAND 40006 diff --git a/src/runner/runner.rc b/src/runner/runner.rc index 18cf1bf8d63c..e683fd10337c 100644 Binary files a/src/runner/runner.rc and b/src/runner/runner.rc differ diff --git a/src/runner/tray_icon.cpp b/src/runner/tray_icon.cpp index ad5946341528..d36667a29614 100644 --- a/src/runner/tray_icon.cpp +++ b/src/runner/tray_icon.cpp @@ -78,6 +78,15 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam case ID_SETTINGS_MENU_COMMAND: open_settings_window(); break; + case ID_IMAGE_RESIZER_COMMAND: + start_image_resizer(); + break; + case ID_WINDOW_WALKER_COMMAND: + start_window_walker(); + break; + case ID_CHECK_FOR_UPDATES_COMMAND: + start_check_for_updates(); + break; case ID_EXIT_MENU_COMMAND: if (h_menu) { @@ -206,3 +215,36 @@ void stop_tray_icon() SendMessage(tray_icon_hwnd, WM_CLOSE, 0, 0); } } + +void start_check_for_updates() +{ + ShellExecute(NULL, NULL, L"https://github.com/microsoft/PowerToys/releases", NULL, NULL, SW_SHOW); +} + +void start_image_resizer() +{ + start_exe_file(const_cast(L".\\modules\\ImageResizer.exe")); +} + +void start_window_walker() +{ + start_exe_file(const_cast(L".\\modules\\WindowWalker.exe")); +} + +void start_exe_file(wchar_t* path) +{ + STARTUPINFO info = { sizeof(info) }; + PROCESS_INFORMATION processInfo; + if (CreateProcess(path, NULL, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo)) + { + //WaitForSingleObject(processInfo.hProcess, INFINITE); // Cannot open more than one window during the program is running + CloseHandle(processInfo.hProcess); + CloseHandle(processInfo.hThread); + } + else + { + MessageBox(NULL, L"Please report the bug to\nhttps://github.com/microsoft/PowerToys/issues\n", L"Error", MB_OK); + } + + /*ShellExecute(NULL, NULL, L".\\modules\\ImageResizer.exe", NULL, NULL, SW_SHOW);*/ // Can open more than one window during the program is running +} diff --git a/src/runner/tray_icon.h b/src/runner/tray_icon.h index 1180bc5e715f..c196cd853230 100644 --- a/src/runner/tray_icon.h +++ b/src/runner/tray_icon.h @@ -1,4 +1,6 @@ #pragma once +#include +#include // Start the Tray Icon void start_tray_icon(); // Stop the Tray Icon @@ -9,3 +11,11 @@ void open_settings_window(); typedef void (*main_loop_callback_function)(PVOID); // Calls a callback in _callback bool dispatch_run_on_main_ui_thread(main_loop_callback_function _callback, PVOID data); +// Start .exe file +void start_exe_file(wchar_t* path); +// Open url check for updates +void start_check_for_updates(); +// Open Image Resizer +void start_image_resizer(); +// Open Window Walker +void start_window_walker(); diff --git a/src/tests/win-app-driver/ImageResizerOpeningTwiceTest.cs b/src/tests/win-app-driver/ImageResizerOpeningTwiceTest.cs new file mode 100644 index 000000000000..47569318f8c4 --- /dev/null +++ b/src/tests/win-app-driver/ImageResizerOpeningTwiceTest.cs @@ -0,0 +1,101 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OpenQA.Selenium.Appium.Windows; +using OpenQA.Selenium.Interactions; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace PowerToysTests +{ + [TestClass] + public class ImageResizerOpeningTwiceTest : PowerToysSession + { + // Import the FindWindow API to find our window + [DllImportAttribute("User32.dll")] + private static extern int FindWindow(string className, string windowName); + int hWndOpen = FindWindow(null, "Image Resizer - Open files"); + int hWndImageResizer = FindWindow(null, "Image Resizer"); + private bool isTrayOpened; + [TestMethod] + public void OpenImageResizer() + { + //open tray + trayButton.Click(); + isTrayOpened = true; + + //open PowerToys context menu + WindowsElement pt = session.FindElementByName("PowerToys"); + Assert.IsNotNull(pt); + + new Actions(session).MoveToElement(pt).ContextClick().Perform(); + ShortWait(); + + //open Image Resizer window twice + session.FindElementByXPath("//MenuItem[@Name=\"Image Resizer\"]").Click(); + ShortWait(); + trayButton.Click(); + new Actions(session).MoveToElement(pt).ContextClick().Perform(); + ShortWait(); + session.FindElementByXPath("//MenuItem[@Name=\"Image Resizer\"]").Click(); + ShortWait(); + + //check Open File Dialog window opened + Assert.AreNotEqual(hWndOpen, 0); + ShortWait(); + + //close Open File Dialog window + CloseWindow("Image Resizer - Open files"); + ShortWait(); + + //check Open File Dialog window closed + Assert.AreEqual(hWndOpen, 0); + + //check Image Resizer window opened + Assert.AreNotEqual(hWndImageResizer, 0); + ShortWait(); + + //open Image Resizer window one more time = twice + new Actions(session).MoveToElement(pt).ContextClick().Perform(); + ShortWait(); + session.FindElementByXPath("//MenuItem[@Name=\"Image Resizer\"]").Click(); + ShortWait(); + + //close Image Resizer window + CloseWindow("Image Resizer"); + ShortWait(); + + //check Image Resizer Closed + Assert.AreEqual(hWndImageResizer, 0); + + //close Image Resizer include background processes + CloseWindowByProcessName("ImageResizer"); + } + + [ClassInitialize] + public static void ClassInitialize(TestContext context) + { + Setup(context); + } + + [ClassCleanup] + public static void ClassCleanup() + { + TearDown(); + } + + [TestInitialize] + public void TestInitialize() + { + + } + + [TestCleanup] + public void TestCleanup() + { + if (isTrayOpened) + { + trayButton.Click(); + } + } + } +} + diff --git a/src/tests/win-app-driver/PowerToysSession.cs b/src/tests/win-app-driver/PowerToysSession.cs index 490e2bf39e1a..806f491f7f17 100644 --- a/src/tests/win-app-driver/PowerToysSession.cs +++ b/src/tests/win-app-driver/PowerToysSession.cs @@ -7,6 +7,7 @@ using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; using OpenQA.Selenium.Interactions; +using System.Diagnostics; namespace PowerToysTests { @@ -276,5 +277,39 @@ private static void RestoreUserSettings() File.Delete(_zoneSettingsPath); } } + + // Close window by using FindElementByName + public static void CloseWindow(string windowName) + { + try + { + WindowsElement window = session.FindElementByName(windowName); + if (window != null) + { + window.SendKeys(Keys.Alt + Keys.F4); + } + } + catch (Exception) + { + + } + } + + // Close processes by GetProcessesByName + public static void CloseWindowByProcessName(string processName) + { + try + { + Process[] processes = Process.GetProcessesByName(processName); + foreach (Process process in processes) + { + process.Kill(); + } + } + catch (Exception) + { + + } + } } } diff --git a/src/tests/win-app-driver/PowerToysTrayTests.cs b/src/tests/win-app-driver/PowerToysTrayTests.cs index 40be62401400..1411c68b2577 100644 --- a/src/tests/win-app-driver/PowerToysTrayTests.cs +++ b/src/tests/win-app-driver/PowerToysTrayTests.cs @@ -2,6 +2,7 @@ using OpenQA.Selenium.Appium; using OpenQA.Selenium.Appium.Windows; using OpenQA.Selenium.Interactions; +using System.Diagnostics; namespace PowerToysTests { @@ -87,6 +88,81 @@ public void PowerToysExit() Assert.IsNull(powerToys); } + [TestMethod] + public void ImageResizerOpenWithContextMenu() + { + //open tray + trayButton.Click(); + isTrayOpened = true; + + //open PowerToys context menu + WindowsElement pt = session.FindElementByName("PowerToys"); + Assert.IsNotNull(pt); + + new Actions(session).MoveToElement(pt).ContextClick().Perform(); + ShortWait(); + + //open Image Resizer window + session.FindElementByXPath("//MenuItem[@Name=\"Image Resizer\"]").Click(); + ShortWait(); + + //check Open File Dialog window opened + WindowsElement imageResizerOpenWindow = session.FindElementByName("Image Resizer - Open files"); + Assert.IsNotNull(imageResizerOpenWindow); + CloseWindow("Image Resizer - Open files"); + ShortWait(); + + //check Image Resizer window opened + Assert.AreNotEqual(Process.GetProcessesByName("ImageResizer").Length, 0); + CloseWindowByProcessName("ImageResizer"); + } + + [TestMethod] + public void WindowWalkerOpenWithContextMenu() + { + //open tray + trayButton.Click(); + isTrayOpened = true; + + //open PowerToys context menu + WindowsElement pt = session.FindElementByName("PowerToys"); + Assert.IsNotNull(pt); + + new Actions(session).MoveToElement(pt).ContextClick().Perform(); + ShortWait(); + + //open Window Walker + session.FindElementByXPath("//MenuItem[@Name=\"Window Walker\"]").Click(); + ShortWait(); + + //check Window Walker opened + Assert.AreNotEqual(Process.GetProcessesByName("WindowWalker").Length, 0); + CloseWindowByProcessName("WindowWalker"); + } + + [TestMethod] + public void AboutOpenWithContextMenu() + { + //open tray + trayButton.Click(); + isTrayOpened = true; + + //open PowerToys context menu + WindowsElement pt = session.FindElementByName("PowerToys"); + Assert.IsNotNull(pt); + new Actions(session).MoveToElement(pt).ContextClick().Perform(); + ShortWait(); + + //open About window + session.FindElementByXPath("//MenuItem[@Name=\"About\"]").Click(); + ShortWait(); + + //check About window opened + WindowsElement aboutWindow = session.FindElementByName("About PowerToys"); + Assert.IsNotNull(aboutWindow); + CloseWindow("About PowerToys"); + } + [ClassInitialize] public static void ClassInitialize(TestContext context) { diff --git a/src/tests/win-app-driver/win-app-driver.csproj b/src/tests/win-app-driver/win-app-driver.csproj index f60b319afb9c..6fed2c2bfb35 100644 --- a/src/tests/win-app-driver/win-app-driver.csproj +++ b/src/tests/win-app-driver/win-app-driver.csproj @@ -1,121 +1,122 @@ - - - - - - Debug - AnyCPU - {880ED251-9E16-4713-9A70-D35FE0C01669} - Library - Properties - PowerToysTests - PowerToysTests + + + + + + Debug + AnyCPU + {880ED251-9E16-4713-9A70-D35FE0C01669} + Library + Properties + PowerToysTests + PowerToysTests v4.7.2 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 15.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - $(SolutionDir)$(Platform)\$(Configuration)\obj\$(AssemblyName)\ - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - x64 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - x64 - - - - ..\..\..\packages\Appium.WebDriver.4.1.1\lib\net45\Appium.Net.dll - - - ..\..\..\packages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll - True - - - ..\..\..\packages\MSTest.TestFramework.2.1.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll - True - - - ..\..\..\packages\MSTest.TestFramework.2.1.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll - True - - - ..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll - True - - - ..\..\..\packages\DotNetSeleniumExtras.PageObjects.3.11.0\lib\net45\SeleniumExtras.PageObjects.dll - True - - - C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll - - - C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll - - - C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll - - - - - ..\..\..\packages\Selenium.WebDriver.3.141.0\lib\net45\WebDriver.dll - True - - - ..\..\..\packages\Selenium.Support.3.141.0\lib\net45\WebDriver.Support.dll - True - - - + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + $(SolutionDir)$(Platform)\$(Configuration)\obj\$(AssemblyName)\ + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + x64 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + x64 + + + + ..\..\..\packages\Appium.WebDriver.4.1.1\lib\net45\Appium.Net.dll + + + ..\..\..\packages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll + True + + + ..\..\..\packages\MSTest.TestFramework.2.1.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll + True + + + ..\..\..\packages\MSTest.TestFramework.2.1.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + True + + + ..\..\..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + True + + + ..\..\..\packages\DotNetSeleniumExtras.PageObjects.3.11.0\lib\net45\SeleniumExtras.PageObjects.dll + True + + + C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll + + + C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll + + + C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll + + + + + ..\..\..\packages\Selenium.WebDriver.3.141.0\lib\net45\WebDriver.dll + True + + + ..\..\..\packages\Selenium.Support.3.141.0\lib\net45\WebDriver.Support.dll + True + + + - - + + - - - - - - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file