I am trying to use Process.Start (with UseShellExecute=true)
to create an instance of notepad.exe
. The code below runs inside of a COM object called by another program (a voice-input program).
Most of the time the code runs fine and creates the notepad instances as expected as a new top window with the focus. I can open and close and open, open, close, close, notepad windows in random order as expected if I close the notepad windows with a WM_CLOSE message as follows:
Win32.PostMessage(Hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
A Second Way of Closing the Notepad Window
The mainstream third-party voice software also provides a “close window” command that will close the notepad window when it is in the foreground. This method of closing the notepad instance is part of the problem.
The Problem
The problem is that after closing the notepad with the voice command “close window,” the next open operation opens notepad but does not bring it to the foreground. It opens behind Outlook or Chrome and is visible on the taskbar. For some reason, the Process.Start
code does not bring the notepad instance to the foreground after notepad has been closed with the “close window” command. I don't understand why. The Process.Start
code should have no clue how (or if) the previous notepad instance was closed.
The code below tries to SetWindowPos
to force the notepad window to the foreground/top in case Process.Start
did not do the job, but the SetWindowPos
code never fails and the failure message box never appears, even when the problem occurs. (SetWindowPos is only a side issue, since the code normally works fine with WM_CLOSE messages.)
Reproducible on My Machine
Here is a typical pattern that I logged on my machine. FChrome/FOutlook means Chrome or Outlook were the foreground windows for the experiment (both were tried with the same results). No = notepad open, Nc = notepad close (as above), CW = “close window”, and NoXX means failure (notepad did not appear as the top foreground window).
Sequences of operations: open, close, open, "close window", open (notepad open fails NoXX)
FChrome, No, Nc, No, CW, NoXX
FOutlook, No, Nc, No, CW, NoXX
Does anyone know why a window-closing method (maybe SendMessage or Win32.WindowDestroy?) would make Process.Start
fail to bring a new instance of Notepad to the foreground?
// record name of foreground window before the operation
var forehandle = GetForegroundWindow ();
var forenamebefore = WinFuns.GetForegroundWindow ().Title;
// create process to start notepad
var psi = new ProcessStartInfo ();
psi.UseShellExecute = true;
psi.FileName = "notepad.exe";
var proc = Process.Start (psi);
Thread.Sleep (2000);
// get foreground process name after Process.Start - it should be notepad
proc.Refresh (); // refresh before retrieving the handle
IntPtr prochandle = (IntPtr)proc.MainWindowHandle;
var forenameafter = WinFuns.GetForegroundWindow ().Title;
// get the process name of this code
var myhandle = Process.GetCurrentProcess ().MainWindowHandle;
var myname = (new WindowHandle (myhandle)).Title;
// ensure the notepad instance is on top
bool r;
var p = new IntPtr (0);
r = Win32.SetWindowPos (prochandle, p, 0, 0, 0, 0, 3); //window on top
if (!r) MessageBox.Show ($"Failed to set top window position.");
// show before/after/mynames after the operation is complete
var msg = $"Foreground before: {forenamebefore}\n" +
$"Foreground after: {forenameafter}\n" +
$"My name is: {myname}";
MessageBox.Show (msg);