I have a main application which runs a console application. The console application is usually started hidden (ProcessWindowStyle.Hidden
), but for testing purposes I can run it with the window shown.
Within the console application I can have plugins loaded and executed. One of the plugins tries to open a WinForm dialog. It works fine if the console application is visible, but it doesn't work any more if the console is hidden.
I have tried:
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form());
and I also tried the same in a new thread.
Thread t = new System.Threading.Thread(start);
t.Start();
t.Join();
where start()
contains the things before. In addition I tried ShowDialog()
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var f = new Form();
f.ShowDialog();
None of the methods showed the window.
In WinDbg, the native callstack always includes NtUserWaitMessage()
:
0:000> k
ChildEBP RetAddr
0038dd58 7b0d8e08 USER32!NtUserWaitMessage+0x15
And the managed callstack always includes WaitMessage()
, FPushMessageLoop()
and RunMessageLoop()
:
0:000> !clrstack
OS Thread Id: 0x47c4 (0)
ESP EIP
0045e560 76bff5be [InlinedCallFrame: 0045e560] System.Windows.Forms.UnsafeNativeMethods.WaitMessage()
0045e55c 7b0d8e08 System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32, Int32, Int32)
0045e5f8 7b0d88f7 System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
0045e64c 7b0d8741 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)
0045e67c 7b5ee597 System.Windows.Forms.Application.RunDialog(System.Windows.Forms.Form)
0045e690 7b622d98 System.Windows.Forms.Form.ShowDialog(System.Windows.Forms.IWin32Window)
0045e71c 7b622faf System.Windows.Forms.Form.ShowDialog()
How can I show a WinForms form from a hidden console window?
SSCCE:
Compile this as a Windows Form application:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var startInfo = new ProcessStartInfo("Console.exe");
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(startInfo);
}
}
Compile this as the console application:
class Program
{
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var mainForm = new Form();
// Enable next line to make it show
// mainForm.Visible = true;
Application.Run(mainForm);
}
}