Wixsharp: MessageBox hidden by install window

Created on 16 May 2018  路  6Comments  路  Source: oleg-shilo/wixsharp

In my install, I have a ManagedAction which calls a MessageBox.Show. The problem is that this messagebox pops up BEHIND the current install window. Even when trying to send the messagebox a ShowWindow command, I have not succeeded in bringing it to the top (even though it seems to flash in the taskbar). Any suggestions would be appreciated. Thanks

question

All 6 comments

using System;
using System.Linq;
using System.Diagnostics;
using System.Windows.Forms;

sealed class WndProxy : IWin32Window
{
    public WndProxy(IntPtr _hwnd) => Handle = _hwnd;

    #region IWin32Window

    public IntPtr Handle { get; }

    #endregion
}

...

WndProxy installerWindow = null;
var installerProcesses = Process.GetProcessesByName("msiexec");
var installerProcess = installerProcesses.FirstOrDefault(prc => prc.MainWindowTitle.Contains("My Product name"));
if( installerProcess != null ) {
    installerWindow = new WndProxy(installerProcess.MainWindowHandle);
}
foreach( var proc in installerProcesses ) {
    proc.Dispose();
}
MessageBox.Show(installerWindow, "Message text");

Excellent answer.

I am not sure if proc.Dispose() is truly needed. Don't get me wrong it's better to dispose if it is disposable but... I am not sure that it makes any actual difference in this case.

Quite possible. But I adhere to the principle: if there is IDisposable, then Dispose should be called

if there is IDisposable, then Dispose should be called

Fully agree. :)

It worked like a charm. Thank you very much!

Thanks @DarthSidius, now main window can be obtained with the session extension method:
I just reworked the proposed solution a bit and incorporated it into the codebase.

```C#
static void project_BeforeInstall(SetupEventArgs e)
{
MessageBox.Show(e.Session.GetMainWindow(), e.ToString(), "BeforeInstall");
}

// -------------------

public static IWin32Window GetMainWindow(this Session session) =>
Tasks.GetMainWindow("msiexec", p => p.MainWindowTitle.Contains(session.Property("ProductName")));

public static IWin32Window GetMainWindow(string processName, Func filter)
{
var processes = Process.GetProcessesByName(processName);
try
{
return new NativeWindow(processes.FirstOrDefault(filter)?.MainWindowHandle);
}
finally
{
processes.ForEach(x => x.Dispose());
}
}

public class NativeWindow : IWin32Window
{
public NativeWindow(IntPtr? hwnd) => Handle = (hwnd ?? IntPtr.Zero);
public IntPtr Handle { get; }
}

```

Was this page helpful?
0 / 5 - 0 ratings