Windows Console Application Getting Stuck (Needs Key Press) [duplicate] - c#

This question already has answers here:
How and why does QuickEdit mode in Command Prompt freeze applications?
(2 answers)
Closed 6 years ago.
I have a console program that has different components that run like this:
void start() {
while(true){
DoSomething();
Thread.Sleep(1000*5);
}
}
My main entry point looks like [pseudo-ish code]
Thread.Start(Componenet1.Start);
Thread.Start(Componenet2.Start);
while(true){
Console.Writeline("running");
Thread.Sleep(1000*5);
}
There are no Console.Reads anywhere. My problem is SOMETIMES the application will be running great but then stop and if I press any key on the window it will start working again. This happens fairly infrequently but I have this program deployed on 100+ VM's running 24/7 in an automated environment.
Also on the computer I have some AHK scripts and other stuff that manipulate the mouse but not sure if that has anything to do with it.
Also note that sometimes the CPU can really be running at 100% on the machines so maybe thread priority is an issue?
SOLUTION: You need to disable quick edit mode. Here is working C# code to do this:
// http://msdn.microsoft.com/en-us/library/ms686033(VS.85).aspx
[DllImport("kernel32.dll")]
public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
private const uint ENABLE_EXTENDED_FLAGS = 0x0080;
static void Main(string[] args)
{
IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
SetConsoleMode(handle, ENABLE_EXTENDED_FLAGS);

If the user accidentally clicks into the black console window, the cursor changes to a filled white rectangle, and the app hangs at the next Console.Write statement, until another clic is made.
It is a generic feature of the Console window when its "QuickEdit Mode" is enabled.
In order to disable that feature, you should uncheck the "QuickEdit Mode" option of your app's console window at run-time.

Related

Get the window handle of the Windows setup process

I am trying to automate Windows 10 installation by first mounting the .iso file on the drive. And then using c# to start windows 10 installation by using this below code which passes the keys to the installation application
[DllImport("user32.dll")]
static extern int SetForegroundWindow(IntPtr point);
public static void Main(String[] args){
Process p1 = Process.Start("h:\\setup.exe");
IntPtr h = p1.MainWindowHandle;
SetForegroundWindow(h);
Thread.Sleep(30000);
SendKeys.SendWait("{ENTER}");
Thread.Sleep(1000);
SendKeys.SendWait("{ENTER}");
Thread.Sleep(1000);
SendKeys.SendWait("{ENTER}");
}
But the problem is that the setup window is not taking the signal of the ENTER key in the code. The setup window is starting with this code. After that, nothing is happening.
Process p1 = Process.Start("h:\\setup.exe");
I tried using notepad instead of setup.exe in the code which is taking all the ENTER keys. Please tell me if anyone has a solution. Thank you
Disclaimer:
I would advise against automating a Windows setup using something like
SendKeys as you can't guarantee a consistent behavior and could
easily mess things up. You may consider looking for different
approaches as suggested by lan Kemp in the comments. This answer
only shows you how to get the handle of the setup window correctly.
You may use it at your own risk.
Update:
Apparently, the Windows 10 setup executable ("Setup.exe") starts another process called "SetupPrep.exe" which starts a third process called "SetupHost.exe" (the one you're after). So, what you can do is start the main process, wait for the target process to start and obtain a MainWindowHandle before executing the remaining code:
Process p1 = Process.Start("H:\\setup.exe");
Process targetProcess;
do
{
Thread.Sleep(500);
targetProcess = Process.GetProcessesByName("SetupHost").FirstOrDefault();
} while (targetProcess == null || targetProcess.MainWindowHandle == IntPtr.Zero);
IntPtr h = targetProcess.MainWindowHandle;
// ...
This should solve your problem, however, it's not a wise idea to use SendKeys for this purpose. Please refer to the disclaimer above.
Original answer:
Did you make sure that h does actually have a value (other than IntPtr.Zero)? Because it probably doesn't have the actual window handle since you don't give the process enough time to start and obtain a window handle.
Try something like this:
Process p1 = Process.Start("h:\\setup.exe");
while (p1.MainWindowHandle == IntPtr.Zero)
{
Thread.Sleep(500);
}
IntPtr h = p1.MainWindowHandle;
// ...

How to be dynamically either console application or Windows Application

I have a small application who should be executed in two modes: non UI or WPF Window. It should depend on command line arguments.
In each mode, I need to show some feedback log:
In WPF Window mode, WPF is going to take care of visualizing logs,
In no UI mode, I need a console to show logs. If my app have been started from a console (mainly cmd.exe), I'd like to use it without opening a new one. If my app have been started outside of a console (double click on explorer, a CreateProcess, ...), I need to create a new console to output my results and wait for a Readkey to close it.
I have found:
how I can create a new console:
How to open/close console window dynamically from a wpf application?,
how to get current console windows handle to show/hide it:
Show/Hide the console window of a C# console application
And I know I can statically choose between "Windows Application" or "Console Application" in project property.
Choosing "Windows Application", GetConsoleWindow() is always 0 and I don't see how to reuse a previous console.
Choosing "Console Application", I can reuse a previous console but when started from explorer in WPF Window mode, a console is created under my WPF main window.
The question is: how can an application be really dynamic? Either in WPF Window mode, with only a WPF windows (and no console at all) or in non UI, with only one console (starting one or a new created one).
It was a lot easier in Winforms, but its not too hard.
Start off with a WPF Application Project (not a console application project with WPF windows).
Create a new Program.cs class in the root directory, add the following code:
class Program
{
[DllImport("Kernel32")]
public static extern void AllocConsole();
[DllImport("Kernel32")]
public static extern void FreeConsole();
[DllImport("kernel32.dll")]
static extern bool AttachConsole(uint dwProcessId);
[STAThread]
public static void Main(string[] args)
{
bool madeConsole = false;
if (args.Length > 0 && args[0] == "console")
{
if (!AttachToConsole())
{
AllocConsole();
Console.WriteLine("Had to create a console");
madeConsole = true;
}
Console.WriteLine("Now I'm a console app!");
Console.WriteLine("Press any key to exit");
Console.ReadKey(true);
if (madeConsole)
FreeConsole();
}
else
{
WpfApplication1.App.Main();
}
}
public static bool AttachToConsole()
{
const uint ParentProcess = 0xFFFFFFFF;
if (!AttachConsole(ParentProcess))
return false;
Console.Clear();
Console.WriteLine("Attached to console!");
return true;
}
}
Now you have a console app or a WPF app. In the Properties, set the start up object as the Program.Main method. In the example above, WpfApplication1.App.Main is the old start up object (defined in the App.xaml.cs file).
Edit this misses one of your requirements about using the existing console and I will edit it as soon as I figure out how to stay in the same console window.
New Edit Now works to use the existing console!

Writing output to the console from a c# winforms application [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I show console output/window in a forms application?
Is there a way for a c# winforms program to write to the console window?
There are basically two things that can happen here.
Console output
It is possible for a winforms program to attach itself to the console window that created it (or to a different console window, or indeed to a new console window if desired). Once attached to the console window Console.WriteLine() etc works as expected. One gotcha to this approach is that the program returns control to the console window immediately, and then carries on writing to it, so the user can also type away in the console window. You can use start with the /wait parameter to handle this I think.
Start commsnd syntax
Redirected console output
This is when someone pipes the output from your program somewhere else, eg.
yourapp > file.txt
Attaching to a console window in this case effectively ignores the piping. To make this work you can call Console.OpenStandardOutput() to get a handle to the stream that the output should be piped to. This only works if the output is piped, so if you want to handle both of the scenarios you need to open the standard output and write to it and attach to the console window. This does mean that the output is sent to the console window and to the pipe but its the best solution I could find. Below the code I use to do this.
// This always writes to the parent console window and also to a redirected stdout if there is one.
// It would be better to do the relevant thing (eg write to the redirected file if there is one, otherwise
// write to the console) but it doesn't seem possible.
public class GUIConsoleWriter : IConsoleWriter
{
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AttachConsole(int dwProcessId);
private const int ATTACH_PARENT_PROCESS = -1;
StreamWriter _stdOutWriter;
// this must be called early in the program
public GUIConsoleWriter()
{
// this needs to happen before attachconsole.
// If the output is not redirected we still get a valid stream but it doesn't appear to write anywhere
// I guess it probably does write somewhere, but nowhere I can find out about
var stdout = Console.OpenStandardOutput();
_stdOutWriter = new StreamWriter(stdout);
_stdOutWriter.AutoFlush = true;
AttachConsole(ATTACH_PARENT_PROCESS);
}
public void WriteLine(string line)
{
_stdOutWriter.WriteLine(line);
Console.WriteLine(line);
}
}

Why does closing a console that was started with AllocConsole cause my whole application to exit? Can I change this behavior?

What I want to have happen is that the console window just goes away, or better yet that it is hidden, but I want my application to keep running. Is that possible? I want to be able to use Console.WriteLine and have the console serve as an output window. I want to be able to hide and show it, and I don't want the whole app to die just because the console was closed.
EDIT
Code:
internal class SomeClass {
[DllImport("kernel32")]
private static extern bool AllocConsole();
private static void Main() {
AllocConsole();
while(true) continue;
}
}
EDIT 2
I tried the accepted solution here [ Capture console exit C# ], per the suggestion in the comments on this question. The example code is bugged in that the DLLImport needs to be "kernel32.dll" or "kernel32", not "Kernel32". After making that change, I'm getting a message to my handler for CTRL_CLOSE_EVENT when I click the X on the console window. However, calling FreeConsole and/or returning true doesn't prevent the application from terminating.
Ah, yes, this is one of the caveats of using the Windows console subsystem. When the user closes the console window (regardless of how the console was allocated), all of the processes that are attached to the console are terminated. That behavior makes obvious sense for console applications (i.e., those that specifically target the console subsystem, as opposed to standard Windows applications), but it can be a major pain in cases like yours.
The only workaround that I know of is to use the SetConsoleCtrlHandler function, which allows you to register a handler function for Ctrl+C and Ctrl+Break signals, as well as system events like the user closing the console window, the user logging off, or the system shutting down. The documentation says that if you're only interested in ignoring these events, you can pass null for the first argument. For example:
[DllImport("kernel32")]
static extern bool SetConsoleCtrlHandler(HandlerRoutine HandlerRoutine, bool Add);
delegate bool HandlerRoutine(uint dwControlType);
static void Main()
{
AllocConsole();
SetConsoleCtrlHandler(null, true);
while (true) continue;
}
That works perfectly for Ctrl+C and Ctrl+Break signals (which would have otherwise caused your application to terminate as well), but it doesn't work for the one you're asking about, which is the CTRL_CLOSE_EVENT, generated by the system when the user closes the console window.
Honestly, I don't know how to prevent that. Even the sample in the SDK doesn't actually allow you to ignore the CTRL_CLOSE_EVENT. I tried it in a little test app, and it beeps when you close the window and prints the message, but the process still gets terminated.
Perhaps more worryingly, the documentation makes me think it is not possible to prevent this:
The system generates CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and CTRL_SHUTDOWN_EVENT signals when the user closes the console, logs off, or shuts down the system so that the process has an opportunity to clean up before termination. Console functions, or any C run-time functions that call console functions, may not work reliably during processing of any of the three signals mentioned previously. The reason is that some or all of the internal console cleanup routines may have been called before executing the process signal handler.
It's that last sentence that catches my eye. If the console subsystem starts cleaning up after itself immediately in response to the user attempting to close the window, it may not be possible to halt it after the fact.
(At least now you understand the problem. Maybe someone else can come along with a solution!)
Unfortunately there's nothing you can do to really alter this behaviour.
Console windows are "special" in that they're hosted by another process and do not allow sub-classing. This limits your ability to modify their behaviour.
From what I know, your two options are:
1. Disable the close button altogether. You can do this with the following code fragment:
HWND hwnd = ::GetConsoleWindow();
if (hwnd != NULL)
{
HMENU hMenu = ::GetSystemMenu(hwnd, FALSE);
if (hMenu != NULL) DeleteMenu(hMenu, SC_CLOSE, MF_BYCOMMAND);
}
2. Stop using consoles altogether, and implement your own text output solution.
Option #2 is the more complicated option but would provide you the greatest control. I found an article on CodeProject that implements a console-like application using a rich edit control to display the text (rich edit controls have the ability to stream text like the console, so they are well suited to this sort of application).
On closing the console window obtained using AllocConsole or AttachConsole, the associated process will exit. There is no escape from that.
Prior to Windows Vista, closing the console window would present a confirmation dialogue to the user asking him whether the process should be terminated or not but Windows Vista and later do not provide any such dialogue and the process gets terminated.
One possible solution to work around this is avoiding AttachConsole altogether and achieving the desired functionality through other means.
For instance in the case described by OP, console window was needed to output some text on Console using Console static class.
This can be achieved very easily using inter-process communication. For example a console application can be developed to act as an echo server
namespace EchoServer
{
public class PipeServer
{
public static void Main()
{
var pipeServer = new NamedPipeServerStream(#"Com.MyDomain.EchoServer.PipeServer", PipeDirection.In);
pipeServer.WaitForConnection();
StreamReader reader = new StreamReader(pipeServer);
try
{
int i = 0;
while (i >= 0)
{
i = reader.Read();
if (i >= 0)
{
Console.Write(Convert.ToChar(i));
}
}
}
catch (IOException)
{
//error handling code here
}
finally
{
pipeServer.Close();
}
}
}
}
and then instead of allocating/attaching a console to the current application, the echo server can be started from within the application and Console's output stream can be redirected to write to the pipe server.
class Program
{
private static NamedPipeClientStream _pipeClient;
static void Main(string[] args)
{
//Current application is a Win32 application without any console window
var processStartInfo = new ProcessStartInfo("echoserver.exe");
Process serverProcess = new Process {StartInfo = processStartInfo};
serverProcess.Start();
_pipeClient = new NamedPipeClientStream(".", #"Com.MyDomain.EchoServer.PipeServer", PipeDirection.Out, PipeOptions.None);
_pipeClient.Connect();
StreamWriter writer = new StreamWriter(_pipeClient) {AutoFlush = true};
Console.SetOut(writer);
Console.WriteLine("Testing");
//Do rest of the work.
//Also detect that the server has terminated (serverProcess.HasExited) and then close the _pipeClient
//Also remember to terminate the server process when current process exits, serverProcess.Kill();
while (true)
continue;
}
}
This is just one of the possible solutions. In essence the work around is to allot the console window to its own process so that it can terminate without affecting the parent process.
You can do this by disabling keyboard mouse input by external program called Keyfreez.
you can use it multiple times in your program where no user input required. And if any user input require u can add a process Takskkill /f /IM .
https://www.sordum.org/7921/bluelife-keyfreeze-v1-4-block-keyboard-and-mouse/
Hope this helps all of you

How do I prevent a C# console application from taking priority as the active window?

I'm sorry if this has been asked but I cannot find an answer to it. I may not be searching the right terms.
I have a console program that needs to be run in the background. The user needs the console to stay open white it runs, but need it to not become the active window when it starts. They would like to continue what they are currently working on and not have to minimize the console every time it starts.
This console application runs multiple times, each time with a new console window. How can I "hide" the console behind the current running task/window?
You can programmatically minimize/restore console windows using below code:
using System;
using System.IO;
namespace ConsoleApplication1
{
class Class1
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
private const int SW_MINIMIZE = 6;
private const int SW_MAXIMIZE = 3;
private const int SW_RESTORE = 9;
[STAThread]
static void Main(string[] args)
{
IntPtr winHandle =
System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
ShowWindow(winHandle, SW_MINIMIZE);
System.Threading.Thread.Sleep(2000);
ShowWindow(winHandle, SW_RESTORE);
}
}
}
If you're using Process.Start to start the console app, better use this:
System.Diagnostics.ProcessStartInfo process= new
System.Diagnostics.ProcessStartInfo(#"MyApplication.exe");
process.WindowStyle=System.Diagnostics.ProcessWindowStyle.Minimized;
process.UseShellExecute=false; // Optional
System.Diagnostics.Process.Start(process);
I don't know of a way to prevent the console window from ever displaying. The best approach in a console app is to hide the window, immediately after the app loads. The visual effect is a quick opening of a console window, then it disappears. Maybe not optimal.
A better approach might be to use a Winexe, instead of a console app. Inside the Windows app (maybe a winforms app), never instantiate the first form. Therefore nothing is ever displayed.
This prevents user interaction, but from your description, it sounds like that's what you want.
But I'm not sure you have control over the "console app".

Categories