Show a hidden console again?
-
Hi everyone, we have an GUI application that starts and observes several console processes. Because it can be lots of processes, we are starting these console applications hidden:
Process process = new Process();
process.StartInfo.FileName = dir + @"\ConsoleApp.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();So far so good, no shell is showing up! But if the user closes the user interface (which started these processes) all the console applications are still running. Since they should finish their job, this is more or less ok. But we would like to show each console again, so the user could stop them if necessary or watch output in each shell himself. Any idea how to show the console applications again? The preferred approach would be that each console application can show itself. (So they would pop up again even if the GUI simply crashed) I have looked into the process information, but the
MainWindowHandle
property is set to null for the console applications, so I can't use it to show the shell. That's also true for any other combination of startinfo properties which lead to a hidden console. In contrast, Spy++ shows a hidden window for my hidden console app! So how to obtain the (still hidden) window's handle? Or any other idea how to show these hidden consoles again? Cheers, Roland -
Hi everyone, we have an GUI application that starts and observes several console processes. Because it can be lots of processes, we are starting these console applications hidden:
Process process = new Process();
process.StartInfo.FileName = dir + @"\ConsoleApp.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();So far so good, no shell is showing up! But if the user closes the user interface (which started these processes) all the console applications are still running. Since they should finish their job, this is more or less ok. But we would like to show each console again, so the user could stop them if necessary or watch output in each shell himself. Any idea how to show the console applications again? The preferred approach would be that each console application can show itself. (So they would pop up again even if the GUI simply crashed) I have looked into the process information, but the
MainWindowHandle
property is set to null for the console applications, so I can't use it to show the shell. That's also true for any other combination of startinfo properties which lead to a hidden console. In contrast, Spy++ shows a hidden window for my hidden console app! So how to obtain the (still hidden) window's handle? Or any other idea how to show these hidden consoles again? Cheers, Roland -
Try windows messages. that gets messages accross applications easily AND you let the application itself handle his own properties. hope this helps.
V.
Could you please go into details a little more? What window message would you send to whome? ShowWindow is also just sending SW_SHOW in the end, but I would need to know the window handle of the console application before I can send it there... Cheers, Roland
-
Could you please go into details a little more? What window message would you send to whome? ShowWindow is also just sending SW_SHOW in the end, but I would need to know the window handle of the console application before I can send it there... Cheers, Roland
-
Oh funny reply, dude! Was the question how to send window messages in general? As I said before, you'd have to know who is the recipient for that message, and actually THAT is the problem. A hidden application has no idea about it's main window's hwnd. And a console application cannot set it's window title to make other apps find it by FindWindow with given title.
-
Oh funny reply, dude! Was the question how to send window messages in general? As I said before, you'd have to know who is the recipient for that message, and actually THAT is the problem. A hidden application has no idea about it's main window's hwnd. And a console application cannot set it's window title to make other apps find it by FindWindow with given title.
-
Don't be so impolite. And I gather you haven't understood my reply, at all. I guess you'll have to figure it out for yourself then. I'm sorry I wasn't able to make it more clearer to you. :mad:
V.
Sorry, but from my point of view your post was already inpolite. ;P I know how to google and how to send messages, I am no noob. But if you have no window handle as recipient, you will never send messages anywhere. And the page you linked uses Process'
MainWindowHandle
property which is always NULL for hidden windows. (As written in my initial post, maybe you have only scanned the first lines of it.) No window handle, no chance to send the message. Seems I have really to enumerate over all windows and find the hidden window that belongs to the process... what a hack... -
Hi everyone, we have an GUI application that starts and observes several console processes. Because it can be lots of processes, we are starting these console applications hidden:
Process process = new Process();
process.StartInfo.FileName = dir + @"\ConsoleApp.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();So far so good, no shell is showing up! But if the user closes the user interface (which started these processes) all the console applications are still running. Since they should finish their job, this is more or less ok. But we would like to show each console again, so the user could stop them if necessary or watch output in each shell himself. Any idea how to show the console applications again? The preferred approach would be that each console application can show itself. (So they would pop up again even if the GUI simply crashed) I have looked into the process information, but the
MainWindowHandle
property is set to null for the console applications, so I can't use it to show the shell. That's also true for any other combination of startinfo properties which lead to a hidden console. In contrast, Spy++ shows a hidden window for my hidden console app! So how to obtain the (still hidden) window's handle? Or any other idea how to show these hidden consoles again? Cheers, RolandThere was a post on MSDN about this a while ago, How to obtain a Console Window Handle[^] which uses FindWindow to look for a known window title. It seems ok for Windows XP and I wrote a quick test (with no error checking on the Windows API calls).
public partial class ConsoleControllerForm : Form {
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);[DllImport("user32.dll")]
private static extern IntPtr FindWindowW(
[In] [MarshalAs(UnmanagedType.LPWStr)] String lpClassName,
[In] [MarshalAs(UnmanagedType.LPWStr)] String WindowName);private const String KnownConsoleTitle = "TestApp";
private IntPtr handle;public ConsoleControllerForm() {
InitializeComponent();
}private void StartBtn_Click(object sender, EventArgs e) {
StartProcess();
FindCmd();
}private void FindCmd() {
handle = FindWindowW(null, KnownConsoleTitle);
ShowBtn.Enabled = handle != IntPtr.Zero;
}private void ShowBtn_Click(object sender, EventArgs e) {
ShowWindow(handle, 1); // ShowNormal = 1
}private static void StartProcess() {
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = @"TestApp.exe";
psi.UseShellExecute = true;
psi.CreateNoWindow = false;
psi.WindowStyle = ProcessWindowStyle.Hidden;
Process p = Process.Start(psi);
// Allow process to start. Can't use WaitForIdleInput
Thread.Sleep(1000);
}
}Note the ProcessStartInfo properties are the only combination for which the subsequent ShowWindow actually shows the window and that TestApp.exe explicitly sets it's title to "TestApp" so I know what to look for with FindWindow. I doubt this approach will solve your problem completely but hopefully it's given you a start. Alan.
-
Hi everyone, we have an GUI application that starts and observes several console processes. Because it can be lots of processes, we are starting these console applications hidden:
Process process = new Process();
process.StartInfo.FileName = dir + @"\ConsoleApp.exe";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();So far so good, no shell is showing up! But if the user closes the user interface (which started these processes) all the console applications are still running. Since they should finish their job, this is more or less ok. But we would like to show each console again, so the user could stop them if necessary or watch output in each shell himself. Any idea how to show the console applications again? The preferred approach would be that each console application can show itself. (So they would pop up again even if the GUI simply crashed) I have looked into the process information, but the
MainWindowHandle
property is set to null for the console applications, so I can't use it to show the shell. That's also true for any other combination of startinfo properties which lead to a hidden console. In contrast, Spy++ shows a hidden window for my hidden console app! So how to obtain the (still hidden) window's handle? Or any other idea how to show these hidden consoles again? Cheers, RolandIf your GUI app crashes, I see no way for it to even try to do this beforehand. Are you also developing the console apps? If so, maybe the console app can monitor the existence of the GUI app and hide and reshow itself on its own?
-
There was a post on MSDN about this a while ago, How to obtain a Console Window Handle[^] which uses FindWindow to look for a known window title. It seems ok for Windows XP and I wrote a quick test (with no error checking on the Windows API calls).
public partial class ConsoleControllerForm : Form {
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);[DllImport("user32.dll")]
private static extern IntPtr FindWindowW(
[In] [MarshalAs(UnmanagedType.LPWStr)] String lpClassName,
[In] [MarshalAs(UnmanagedType.LPWStr)] String WindowName);private const String KnownConsoleTitle = "TestApp";
private IntPtr handle;public ConsoleControllerForm() {
InitializeComponent();
}private void StartBtn_Click(object sender, EventArgs e) {
StartProcess();
FindCmd();
}private void FindCmd() {
handle = FindWindowW(null, KnownConsoleTitle);
ShowBtn.Enabled = handle != IntPtr.Zero;
}private void ShowBtn_Click(object sender, EventArgs e) {
ShowWindow(handle, 1); // ShowNormal = 1
}private static void StartProcess() {
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = @"TestApp.exe";
psi.UseShellExecute = true;
psi.CreateNoWindow = false;
psi.WindowStyle = ProcessWindowStyle.Hidden;
Process p = Process.Start(psi);
// Allow process to start. Can't use WaitForIdleInput
Thread.Sleep(1000);
}
}Note the ProcessStartInfo properties are the only combination for which the subsequent ShowWindow actually shows the window and that TestApp.exe explicitly sets it's title to "TestApp" so I know what to look for with FindWindow. I doubt this approach will solve your problem completely but hopefully it's given you a start. Alan.
Hi Alan, thanks for your reply! At the moment I really make use of a combination of
EnumWindows
andGetWindowThreadProcessId
to get my own (hidden) window's handle within the console application. But I am not happy about enumerating over all windows.FindWindow
was also my first thought... the problem was that I had no clue what the title is. The shell usually shows the console application's full path in the title. Having multiple instances running, this can be quite difficult to find a specific one. But you made me think about the window title again, because you really hardcoded a title for a console application. First I thought I could not change it from within the console application itself in C#, sinceMainWindowTitle
is read-only. But then I found the following API method:[DllImportAttribute("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetConsoleTitle(IntPtr lpConsoleTitle);In this case I can easily set the window title; either by passing it as parameter along with
ProcessStartInfo
, or simply generating it within the console itself. Thanks for thought-provoking impulse. :) Cheers, Roland -
If your GUI app crashes, I see no way for it to even try to do this beforehand. Are you also developing the console apps? If so, maybe the console app can monitor the existence of the GUI app and hide and reshow itself on its own?
Yes, we create both, the GUI and the Console Apps. The latter one can be executed manually or started through the UI (invisible). So we are actually realy monitoring the UI, but had no (good) idea how to make the console show itself when the GUI was gone. But as a result of Alan's thought-provoking impulse I have an idea how to do this now. :) Cheers, Roland