diff --git a/src/modules/previewpane/GcodePreviewHandler/Program.cs b/src/modules/previewpane/GcodePreviewHandler/Program.cs
index 0b0696fd01..cddf09cee4 100644
--- a/src/modules/previewpane/GcodePreviewHandler/Program.cs
+++ b/src/modules/previewpane/GcodePreviewHandler/Program.cs
@@ -36,15 +36,24 @@ namespace Microsoft.PowerToys.PreviewHandler.Gcode
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
_previewHandlerControl = new GcodePreviewHandlerControl();
- _previewHandlerControl.SetWindow(hwnd, s);
+
+ if (!_previewHandlerControl.SetWindow(hwnd, s))
+ {
+ return;
+ }
+
_previewHandlerControl.DoPreview(filePath);
NativeEventWaiter.WaitForEventLoop(
Constants.GcodePreviewResizeEvent(),
() =>
{
- Rectangle s = default(Rectangle);
- _previewHandlerControl.SetRect(s);
+ Rectangle s = default;
+ if (!_previewHandlerControl.SetRect(s))
+ {
+ // When the parent HWND became invalid, the application won't respond to Application.Exit().
+ Environment.Exit(0);
+ }
},
Dispatcher.CurrentDispatcher,
_tokenSource.Token);
diff --git a/src/modules/previewpane/GcodePreviewHandlerCpp/GcodePreviewHandler.cpp b/src/modules/previewpane/GcodePreviewHandlerCpp/GcodePreviewHandler.cpp
index 41a4fc202f..3ad3711dd0 100644
--- a/src/modules/previewpane/GcodePreviewHandlerCpp/GcodePreviewHandler.cpp
+++ b/src/modules/previewpane/GcodePreviewHandlerCpp/GcodePreviewHandler.cpp
@@ -159,9 +159,9 @@ IFACEMETHODIMP GcodePreviewHandler::DoPreview()
{
try
{
- if (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0)
+ if (m_hwndParent == NULL || (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0))
{
- // Postponing Start GcodePreviewHandler.exe, position not yet initialized. preview will be done after initialisation
+ // Postponing Start GcodePreviewHandler.exe, parent and position not yet initialized. Preview will be done after initialisation.
return S_OK;
}
Logger::info(L"Starting GcodePreviewHandler.exe");
@@ -189,6 +189,13 @@ IFACEMETHODIMP GcodePreviewHandler::DoPreview()
sei.lpParameters = cmdLine.c_str();
sei.nShow = SW_SHOWDEFAULT;
ShellExecuteEx(&sei);
+
+ // Prevent to leak processes: preview is called multiple times when minimizing and restoring Explorer window
+ if (m_process)
+ {
+ TerminateProcess(m_process, 0);
+ }
+
m_process = sei.hProcess;
}
catch (std::exception& e)
diff --git a/src/modules/previewpane/MarkdownPreviewHandler/Program.cs b/src/modules/previewpane/MarkdownPreviewHandler/Program.cs
index 8b6b66f974..3d5fe7c207 100644
--- a/src/modules/previewpane/MarkdownPreviewHandler/Program.cs
+++ b/src/modules/previewpane/MarkdownPreviewHandler/Program.cs
@@ -36,15 +36,24 @@ namespace Microsoft.PowerToys.PreviewHandler.Markdown
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
_previewHandlerControl = new MarkdownPreviewHandlerControl();
- _previewHandlerControl.SetWindow(hwnd, s);
+
+ if (!_previewHandlerControl.SetWindow(hwnd, s))
+ {
+ return;
+ }
+
_previewHandlerControl.DoPreview(filePath);
NativeEventWaiter.WaitForEventLoop(
Constants.MarkdownPreviewResizeEvent(),
() =>
{
- Rectangle s = default(Rectangle);
- _previewHandlerControl.SetRect(s);
+ Rectangle s = default;
+ if (!_previewHandlerControl.SetRect(s))
+ {
+ // When the parent HWND became invalid, the application won't respond to Application.Exit().
+ Environment.Exit(0);
+ }
},
Dispatcher.CurrentDispatcher,
_tokenSource.Token);
diff --git a/src/modules/previewpane/MarkdownPreviewHandlerCpp/MarkdownPreviewHandler.cpp b/src/modules/previewpane/MarkdownPreviewHandlerCpp/MarkdownPreviewHandler.cpp
index 66970506f3..2837880a42 100644
--- a/src/modules/previewpane/MarkdownPreviewHandlerCpp/MarkdownPreviewHandler.cpp
+++ b/src/modules/previewpane/MarkdownPreviewHandlerCpp/MarkdownPreviewHandler.cpp
@@ -160,9 +160,9 @@ IFACEMETHODIMP MarkdownPreviewHandler::DoPreview()
{
try
{
- if (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0)
+ if (m_hwndParent == NULL || (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0))
{
- // Postponing Start MarkdownPreviewHandler.exe, position not yet initialized. preview will be done after initialisation
+ // Postponing Start MarkdownPreviewHandler.exe, parent and position not yet initialized. Preview will be done after initialisation.
return S_OK;
}
Logger::info(L"Starting MarkdownPreviewHandler.exe");
@@ -190,6 +190,13 @@ IFACEMETHODIMP MarkdownPreviewHandler::DoPreview()
sei.lpParameters = cmdLine.c_str();
sei.nShow = SW_SHOWDEFAULT;
ShellExecuteEx(&sei);
+
+ // Prevent to leak processes: preview is called multiple times when minimizing and restoring Explorer window
+ if (m_process)
+ {
+ TerminateProcess(m_process, 0);
+ }
+
m_process = sei.hProcess;
}
catch (std::exception& e)
diff --git a/src/modules/previewpane/MonacoPreviewHandler/Program.cs b/src/modules/previewpane/MonacoPreviewHandler/Program.cs
index 7821d25658..fabb0ca710 100644
--- a/src/modules/previewpane/MonacoPreviewHandler/Program.cs
+++ b/src/modules/previewpane/MonacoPreviewHandler/Program.cs
@@ -39,15 +39,24 @@ namespace Microsoft.PowerToys.PreviewHandler.Monaco
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
_previewHandlerControl = new MonacoPreviewHandlerControl();
- _previewHandlerControl.SetWindow(hwnd, s);
+
+ if (!_previewHandlerControl.SetWindow(hwnd, s))
+ {
+ return;
+ }
+
_previewHandlerControl.DoPreview(filePath);
NativeEventWaiter.WaitForEventLoop(
Constants.DevFilesPreviewResizeEvent(),
() =>
{
- Rectangle s = default(Rectangle);
- _previewHandlerControl.SetRect(s);
+ Rectangle s = default;
+ if (!_previewHandlerControl.SetRect(s))
+ {
+ // When the parent HWND became invalid, the application won't respond to Application.Exit().
+ Environment.Exit(0);
+ }
},
Dispatcher.CurrentDispatcher,
_tokenSource.Token);
diff --git a/src/modules/previewpane/MonacoPreviewHandlerCpp/MonacoPreviewHandler.cpp b/src/modules/previewpane/MonacoPreviewHandlerCpp/MonacoPreviewHandler.cpp
index 724e140574..004427de69 100644
--- a/src/modules/previewpane/MonacoPreviewHandlerCpp/MonacoPreviewHandler.cpp
+++ b/src/modules/previewpane/MonacoPreviewHandlerCpp/MonacoPreviewHandler.cpp
@@ -159,9 +159,9 @@ IFACEMETHODIMP MonacoPreviewHandler::DoPreview()
{
try
{
- if (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0)
+ if (m_hwndParent == NULL || (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0))
{
- // Postponing Start MonacoPreviewHandler.exe, position not yet initialized. preview will be done after initialisation
+ // Postponing Start MonacoPreviewHandler.exe, parent and position not yet initialized. Preview will be done after initialisation.
return S_OK;
}
@@ -189,6 +189,13 @@ IFACEMETHODIMP MonacoPreviewHandler::DoPreview()
sei.lpParameters = cmdLine.c_str();
sei.nShow = SW_SHOWDEFAULT;
ShellExecuteEx(&sei);
+
+ // Prevent to leak processes: preview is called multiple times when minimizing and restoring Explorer window
+ if (m_process)
+ {
+ TerminateProcess(m_process, 0);
+ }
+
m_process = sei.hProcess;
}
catch (std::exception& e)
diff --git a/src/modules/previewpane/PdfPreviewHandler/Program.cs b/src/modules/previewpane/PdfPreviewHandler/Program.cs
index d9427dc215..7c883b7989 100644
--- a/src/modules/previewpane/PdfPreviewHandler/Program.cs
+++ b/src/modules/previewpane/PdfPreviewHandler/Program.cs
@@ -35,15 +35,24 @@ namespace Microsoft.PowerToys.PreviewHandler.Pdf
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
_previewHandlerControl = new PdfPreviewHandlerControl();
- _previewHandlerControl.SetWindow(hwnd, s);
+
+ if (!_previewHandlerControl.SetWindow(hwnd, s))
+ {
+ return;
+ }
+
_previewHandlerControl.DoPreview(filePath);
NativeEventWaiter.WaitForEventLoop(
Constants.PdfPreviewResizeEvent(),
() =>
{
- Rectangle s = default(Rectangle);
- _previewHandlerControl.SetRect(s);
+ Rectangle s = default;
+ if (!_previewHandlerControl.SetRect(s))
+ {
+ // When the parent HWND became invalid, the application won't respond to Application.Exit().
+ Environment.Exit(0);
+ }
},
Dispatcher.CurrentDispatcher,
_tokenSource.Token);
diff --git a/src/modules/previewpane/PdfPreviewHandlerCpp/PdfPreviewHandler.cpp b/src/modules/previewpane/PdfPreviewHandlerCpp/PdfPreviewHandler.cpp
index 7ad100bbc4..aadc5ce709 100644
--- a/src/modules/previewpane/PdfPreviewHandlerCpp/PdfPreviewHandler.cpp
+++ b/src/modules/previewpane/PdfPreviewHandlerCpp/PdfPreviewHandler.cpp
@@ -147,6 +147,7 @@ IFACEMETHODIMP PdfPreviewHandler::SetRect(const RECT* prc)
}
}
}
+ m_rcParent = *prc;
hr = S_OK;
}
return hr;
@@ -156,9 +157,9 @@ IFACEMETHODIMP PdfPreviewHandler::DoPreview()
{
try
{
- if (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0)
+ if (m_hwndParent == NULL || (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0))
{
- // Postponing Start PdfPreviewHandler.exe, position not yet initialized. preview will be done after initialisation
+ // Postponing Start PdfPreviewHandler.exe, parent and position not yet initialized. Preview will be done after initialisation.
return S_OK;
}
Logger::info(L"Starting PdfPreviewHandler.exe");
@@ -186,6 +187,13 @@ IFACEMETHODIMP PdfPreviewHandler::DoPreview()
sei.lpParameters = cmdLine.c_str();
sei.nShow = SW_SHOWDEFAULT;
ShellExecuteEx(&sei);
+
+ // Prevent to leak processes: preview is called multiple times when minimizing and restoring Explorer window
+ if (m_process)
+ {
+ TerminateProcess(m_process, 0);
+ }
+
m_process = sei.hProcess;
}
catch (std::exception& e)
diff --git a/src/modules/previewpane/QoiPreviewHandler/Program.cs b/src/modules/previewpane/QoiPreviewHandler/Program.cs
index 5a9f5bfa2b..469d0c3b25 100644
--- a/src/modules/previewpane/QoiPreviewHandler/Program.cs
+++ b/src/modules/previewpane/QoiPreviewHandler/Program.cs
@@ -36,15 +36,24 @@ namespace Microsoft.PowerToys.PreviewHandler.Qoi
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
_previewHandlerControl = new QoiPreviewHandlerControl();
- _previewHandlerControl.SetWindow(hwnd, s);
+
+ if (!_previewHandlerControl.SetWindow(hwnd, s))
+ {
+ return;
+ }
+
_previewHandlerControl.DoPreview(filePath);
NativeEventWaiter.WaitForEventLoop(
Constants.QoiPreviewResizeEvent(),
() =>
{
- Rectangle s = default(Rectangle);
- _previewHandlerControl.SetRect(s);
+ Rectangle s = default;
+ if (!_previewHandlerControl.SetRect(s))
+ {
+ // When the parent HWND became invalid, the application won't respond to Application.Exit().
+ Environment.Exit(0);
+ }
},
Dispatcher.CurrentDispatcher,
_tokenSource.Token);
diff --git a/src/modules/previewpane/QoiPreviewHandlerCpp/QoiPreviewHandler.cpp b/src/modules/previewpane/QoiPreviewHandlerCpp/QoiPreviewHandler.cpp
index 9d1ce0a813..7cf8873bba 100644
--- a/src/modules/previewpane/QoiPreviewHandlerCpp/QoiPreviewHandler.cpp
+++ b/src/modules/previewpane/QoiPreviewHandlerCpp/QoiPreviewHandler.cpp
@@ -159,9 +159,9 @@ IFACEMETHODIMP QoiPreviewHandler::DoPreview()
{
try
{
- if (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0)
+ if (m_hwndParent == NULL || (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0))
{
- // Postponing Start QoiPreviewHandler.exe, position not yet initialized. preview will be done after initialisation
+ // Postponing Start QoiPreviewHandler.exe, parent and position not yet initialized. Preview will be done after initialisation.
return S_OK;
}
Logger::info(L"Starting QoiPreviewHandler.exe");
@@ -189,6 +189,13 @@ IFACEMETHODIMP QoiPreviewHandler::DoPreview()
sei.lpParameters = cmdLine.c_str();
sei.nShow = SW_SHOWDEFAULT;
ShellExecuteEx(&sei);
+
+ // Prevent to leak processes: preview is called multiple times when minimizing and restoring Explorer window
+ if (m_process)
+ {
+ TerminateProcess(m_process, 0);
+ }
+
m_process = sei.hProcess;
}
catch (std::exception& e)
diff --git a/src/modules/previewpane/SvgPreviewHandler/Program.cs b/src/modules/previewpane/SvgPreviewHandler/Program.cs
index 4b506ded1a..e46e9f784c 100644
--- a/src/modules/previewpane/SvgPreviewHandler/Program.cs
+++ b/src/modules/previewpane/SvgPreviewHandler/Program.cs
@@ -36,15 +36,24 @@ namespace Microsoft.PowerToys.PreviewHandler.Svg
Rectangle s = new Rectangle(left, top, right - left, bottom - top);
_previewHandlerControl = new SvgPreviewControl();
- _previewHandlerControl.SetWindow(hwnd, s);
+
+ if (!_previewHandlerControl.SetWindow(hwnd, s))
+ {
+ return;
+ }
+
_previewHandlerControl.DoPreview(filePath);
NativeEventWaiter.WaitForEventLoop(
Constants.SvgPreviewResizeEvent(),
() =>
{
- Rectangle s = default(Rectangle);
- _previewHandlerControl.SetRect(s);
+ Rectangle s = default;
+ if (!_previewHandlerControl.SetRect(s))
+ {
+ // When the parent HWND became invalid, the application won't respond to Application.Exit().
+ Environment.Exit(0);
+ }
},
Dispatcher.CurrentDispatcher,
_tokenSource.Token);
diff --git a/src/modules/previewpane/SvgPreviewHandlerCpp/SvgPreviewHandler.cpp b/src/modules/previewpane/SvgPreviewHandlerCpp/SvgPreviewHandler.cpp
index 174163f77a..e0c257db49 100644
--- a/src/modules/previewpane/SvgPreviewHandlerCpp/SvgPreviewHandler.cpp
+++ b/src/modules/previewpane/SvgPreviewHandlerCpp/SvgPreviewHandler.cpp
@@ -149,6 +149,7 @@ IFACEMETHODIMP SvgPreviewHandler::SetRect(const RECT* prc)
}
}
}
+ m_rcParent = *prc;
hr = S_OK;
}
return hr;
@@ -158,9 +159,9 @@ IFACEMETHODIMP SvgPreviewHandler::DoPreview()
{
try
{
- if (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0)
+ if (m_hwndParent == NULL || (m_rcParent.left == 0 && m_rcParent.top == 0 && m_rcParent.right == 0 && m_rcParent.bottom == 0))
{
- // Postponing Start SvgPreviewHandler.exe, position not yet initialized. preview will be done after initialisation
+ // Postponing Start SvgPreviewHandler.exe, parent and position not yet initialized. Preview will be done after initialisation.
return S_OK;
}
Logger::info(L"Starting SvgPreviewHandler.exe");
@@ -188,6 +189,13 @@ IFACEMETHODIMP SvgPreviewHandler::DoPreview()
sei.lpParameters = cmdLine.c_str();
sei.nShow = SW_SHOWDEFAULT;
ShellExecuteEx(&sei);
+
+ // Prevent to leak processes: preview is called multiple times when minimizing and restoring Explorer window
+ if (m_process)
+ {
+ TerminateProcess(m_process, 0);
+ }
+
m_process = sei.hProcess;
}
catch (std::exception& e)
diff --git a/src/modules/previewpane/common/cominterop/NativeMethods.cs b/src/modules/previewpane/common/cominterop/NativeMethods.cs
index 611136b1a3..58979d0ff8 100644
--- a/src/modules/previewpane/common/cominterop/NativeMethods.cs
+++ b/src/modules/previewpane/common/cominterop/NativeMethods.cs
@@ -37,5 +37,8 @@ namespace PreviewHandlerCommon.ComInterop
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetClientRect(IntPtr hWnd, ref Common.ComInterlop.RECT rect);
+
+ [DllImport("user32.dll")]
+ public static extern bool IsWindow(IntPtr hWnd);
}
}
diff --git a/src/modules/previewpane/common/controls/FormHandlerControl.cs b/src/modules/previewpane/common/controls/FormHandlerControl.cs
index ef798ed424..dd3cd9f897 100644
--- a/src/modules/previewpane/common/controls/FormHandlerControl.cs
+++ b/src/modules/previewpane/common/controls/FormHandlerControl.cs
@@ -73,9 +73,9 @@ namespace Common
}
///
- public void SetRect(Rectangle windowBounds)
+ public bool SetRect(Rectangle windowBounds)
{
- this.UpdateWindowBounds(parentHwnd, windowBounds);
+ return this.UpdateWindowBounds(parentHwnd, windowBounds);
}
///
@@ -85,10 +85,10 @@ namespace Common
}
///
- public void SetWindow(IntPtr hwnd, Rectangle rect)
+ public bool SetWindow(IntPtr hwnd, Rectangle rect)
{
this.parentHwnd = hwnd;
- this.UpdateWindowBounds(hwnd, rect);
+ return this.UpdateWindowBounds(hwnd, rect);
}
///
@@ -118,12 +118,18 @@ namespace Common
///
/// Update the Form Control window with the passed rectangle.
///
- public void UpdateWindowBounds(IntPtr hwnd, Rectangle newBounds)
+ public bool UpdateWindowBounds(IntPtr hwnd, Rectangle newBounds)
{
+ if (hwnd == IntPtr.Zero || !NativeMethods.IsWindow(hwnd))
+ {
+ // If the HWND is IntPtr.Zero the desktop window will be used as parent.
+ return false;
+ }
+
if (this.Disposing || this.IsDisposed)
{
// For unclear reasons, this can be called when handling an error and the form has already been disposed.
- return;
+ return false;
}
// We must set the WS_CHILD style to change the form to a control within the Explorer preview pane
@@ -133,7 +139,10 @@ namespace Common
_ = NativeMethods.SetWindowLong(Handle, gwlStyle, windowStyle | wsChild);
}
- NativeMethods.SetParent(Handle, hwnd);
+ if (NativeMethods.SetParent(Handle, hwnd) == IntPtr.Zero)
+ {
+ return false;
+ }
if (newBounds.IsEmpty)
{
@@ -146,6 +155,8 @@ namespace Common
{
Bounds = newBounds;
}
+
+ return true;
}
}
}
diff --git a/src/modules/previewpane/common/controls/IPreviewHandlerControl.cs b/src/modules/previewpane/common/controls/IPreviewHandlerControl.cs
index a5e074b8db..c0b7bc291f 100644
--- a/src/modules/previewpane/common/controls/IPreviewHandlerControl.cs
+++ b/src/modules/previewpane/common/controls/IPreviewHandlerControl.cs
@@ -58,14 +58,16 @@ namespace Common
/// Directs the control to change the area within the parent hwnd that it draws into.
///
/// Instance of Rectangle defining the area.
- void SetRect(Rectangle windowBounds);
+ /// if the operation was successful; otherwise, .
+ bool SetRect(Rectangle windowBounds);
///
- /// Sets the parent window of the previewer window, as well as the area within the parent to be used for the previewer window..
+ /// Sets the parent window of the previewer window, as well as the area within the parent to be used for the previewer window.
///
/// Pointer to the parent window handle.
/// Instance of Rectangle defining the area.
- void SetWindow(IntPtr hwnd, Rectangle rect);
+ /// if the operation was successful; otherwise, .
+ bool SetWindow(IntPtr hwnd, Rectangle rect);
///
/// Called by Preview Handler to start the preview.