Question

I'm trying to do the following in C#:

  • Open a new process (notepad.exe)
  • Enter some text (using SendKeys)
  • Close Notepad (deal with any confirmation dialogs)

Here's what I got

Process p = new Process();
p.StartInfo.Filename = "notepad.exe";
p.Start();

// use the user32.dll SetForegroundWindow method
SetForegroundWindow( p.MainWindowHandle ); // make sure notepad has focus

SendKeys.SendWait( "some text" );

SendKeys.SendWait( "%f" ); // send ALT+f
SendKeys.SendWait( "x" ); // send x = exit

// a confirmation dialog appears

All this works just as expected, but now after I've sent ALT+f+x I get a "Do you want to save changed to Untitled" dialog and I would like to close it from within my applications by "pressing" 'n' for "Don't Save". However

SendKeys.SendWait( "n" ); 

works only if my application has not lost focus (after ALT+f+x). If it did and I try to go back using

SetForegroundWindow( p.MainWindowHandle );

this sets the focus to the main notepad window instead of the confirmation dialog. I used the GetForegroundWindow method from user32.dll and found out that the dialog handle is different than the notepad handle (which kinda makes sence) but SetForegroundWindow doesn't work with even with the dialog window handle

Any idea how I can give the focus back to the dialog so that I can successfully use SendKeys?

here's the full code

[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);        

[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();             

[DllImport("User32.DLL")] 
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); 

public const int SW_RESTORE = 9;        

    ...

Process p = new Process();
p.StartInfo.FileName = "notepad.exe";
p.Start();
Thread.Sleep( 1000 );

SendKeys.SendWait( "some text" );
SendKeys.SendWait( "%f" ); // send ALT+F
SendKeys.SendWait( "x" ); // send x = exit

IntPtr dialogHandle = GetForegroundWindow();
System.Diagnostics.Trace.WriteLine( "notepad handle: " + p.MainWindowHandle );
System.Diagnostics.Trace.WriteLine( "dialog handle: " + dialogHandle );

Thread.Sleep( 5000 ); // switch to a different application to lose focus

SetForegroundWindow( p.MainWindowHandle );
ShowWindow( dialogHandle, SW_RESTORE );

Thread.Sleep( 1000 );
SendKeys.SendWait( "n" );

Thank you

Was it helpful?

Solution

You can't give what you don't have - SetForegroundWindow() only works if your application currently has the focus.

Modern Windows versions prevent applications from stealing focus, as that was a major annoyance back in the Windows 9x days.

Also, 'Alt+F, x' only refers to exit on English Windows versions, it won't work on most other languages. Avoid using SendKeys(), it's impossible to use in a reliable way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top