I have been researching in how to stop a console application when pressing esc (or any key really.
I ran into this solution
Listen for key press in .NET console app
Now, I was trying to apply it to my case:
I should stop my console app, which is a loop, when I press any key.
Coming from the solution provided in the topic above, I added my own part as follows:
Console.WriteLine("Press ESC to stop");
do {
while (! Console.KeyAvailable) {
foreach (var station in WeatherStations.station)
{
var stationAirParams = station.value?.FirstOrDefault();
Console.WriteLine(
station.name + " " + (stationAirParams == null
? ""
: stationAirParams.value)
);
Thread.Sleep(100);
}
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
That said... why isn't the loop stopping?
Your approach uses polling in a single thread, and it is not event driven.
The inner loop won't stop on key press. It will simply finish its work before the code checks for key press for the first time in the outer loops.
Move an abort condition like the following
if(Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.Escape)
{
break;
}
to the innermost loop.
There is another answer here which shows how to spawn a background thread to do the work whilst waiting for a keypress to exit on the main thread.
i made an app and sometimes it just pauses until I press a key.
i do not use any code which requiereres any input or interaction (such as readline or readkey).
this randomly happens like 1 in 20 times after Thread.Sleep and after you press any key it continues to work perfectly.
if (Convert.ToInt64(timetotask[0]) > 0)
{
Thread.Sleep(Convert.ToInt32(timetotask[0]));
}
else
{
mylog.log("Task was in the past, executing it now");
}
int currentbid = placebid(task.itemid, bid, driver[Convert.ToInt32(task.account)]);
the first line of placebid is console.writeline("mystring") so i do not see anything what could cause this behaviour.
Does it have something to do with debug mode?
thanks for help
This could be obvious but if pressing a key in the console makes the application resume, it is most likely you managed to pause the app via the console by pressing a key.
When it is sleeping do you ever press a key to check if it has paused? Then eventually the sleep ends as it matches the rule and then when you next press a key it unpauses the program...
Michael
Im new to C#!
So my Problem: I got a C# Demo Program from an extern company, the program sets the settings of an extern device, than initialize it and starts recording the Data. The Data is written into the Console and streamed into a CSV at a Location i can choose. After pressing a Key in the Console the Recording stops. I am trying now to write a short GUI that starts and stops this Recording.
What I did:
I converted the main-method, which started the recoding, into a normal static method and deleted all writelines so the console doesnt start, than I created a Windows Form with 2 Buttons, one Start and One Stop. If I press Start, the Recording starts, but I cant do anything with the Gui it is like freeezed, a Console still appeares and i can only stop the process by pressing a key in the console.
Here is a snippit of the Console Code:
class BHJKL
{
system
private static A;
private static B;
// This method will be executed every time new data is received
static void OnNewDataReceived(object sender, NewDataEventArgs eventArgs)
{
//some code in here
using (StreamWriter file = new StreamWriter(#"C:\Users\XYZ\File_Trial" + DateTime.Now.DayOfYear + ".csv", true))
{
//Writeline data..
}
}
}
// This was the Main Method before i changed it
public static void Record()
{
// Here is some Code that configure the Settings of the device
// initialize device
// MORE CODE USING THE COMPANYS EXTERN LIBRARYS TO START THE DEVICE
//start device
deviceManager.DeviceStart();
while (!Console.KeyAvailable) // as long as no key is pressed do...
{
Thread.Sleep(100); // do nothing, let the event processing thread that is managed by the library handle incomming data
}
//stop device
deviceManager.DeviceStop();
//unsubscribe event
deviceManager.NewDataReceived -= OnNewDataReceived;
//deinitialize device
deviceManager.DeinitializeDevice();
//dispose device
deviceManager.Dispose();
}
}
My Attempt:
Changing the main method into static Recording.
Than by Pressing the Start Button, call the method.
Write this at the end of the method:
while (Rec==true)
{
Thread.Sleep(100);
}
By Pressing the Stop Button: set.Rec(false)
But after Pressing the start Button, i cant press the stop button anyome.
I hope someone can understand my Problem and can give me some advices.
Thread.Sleep blocks your UI from doing anything. Consider using a System.Windows.Forms.Timer
Rather than sleeping in a loop, you should just let your Start method return. Move all of the code that comes after the sleep loop into your Stop button's click event handler.
(Depending on how the code is structured, you may also have to switch deviceManager from being a local variable to being a field in the class)
I'm writing an console application witch Displaying certain data on the console screen, than checking for user input from the keyboard and finally handleing it by need. all single threaded.
For that i tried using Keyboard.IsKeyDown Method from System.Windows.Input namespace. and visual studio wo'nt allow it.
Does anyone knows why and can help me?
I dont see other way implementing that logic using only one thread and no timer's.
Use Console.ReadKey() to read input from the keyboard in a console application.
Note that this is a blocking call. If you don't want to block, combine with Console.KeyAvailable. For example, this program will loop and display if a key is pressed every 10th of a second:
static void Main(string[] args)
{
do
{
if (Console.KeyAvailable)
{
var key = Console.ReadKey();
Console.WriteLine(key.Key);
}
else
{
Console.WriteLine("No key pressed");
}
System.Threading.Thread.Sleep(100);
} while (true);
}
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