How to Programmatic Disable C# Console Application's Quick Edit Mode

How to programmatic disable C# Console Application's Quick Edit mode?

If you want to disable quick edit mode, you need to call GetConsoleMode to get the current mode. Then clear the bit that enables quick edit, and call SetConsoleMode. Assuming you have the managed prototypes for the unmanaged functions, you would write:

const int ENABLE_QUICK_EDIT = 0x0040;

IntPtr consoleHandle = GetConsoleWindow();
UInt32 consoleMode;

// get current console mode
if (!GetConsoleMode(consoleHandle, out consoleMode))
{
// Error: Unable to get console mode.
return;
}

// Clear the quick edit bit in the mode flags
mode &= ~ENABLE_QUICK_EDIT;

// set the new mode
if (!SetConsoleMode(consoleHandle, consoleMode))
{
// ERROR: Unable to set console mode
}

If you want to disable mouse input, you want to clear the mouse input bit.

const int ENABLE_MOUSE_INPUT = 0x0010;

mode &= ~ENABLE_MOUSE_INPUT;

Show/Hide the console window of a C# console application

Here’s how:

using System.Runtime.InteropServices;

[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();

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

const int SW_HIDE = 0;
const int SW_SHOW = 5;

var handle = GetConsoleWindow();

// Hide
ShowWindow(handle, SW_HIDE);

// Show
ShowWindow(handle, SW_SHOW);

How to enable Windows console QuickEdit Mode from python?

You can use ctypes to call GetConsoleMode and SetConsoleMode.

ctypes definitions:

import msvcrt
import atexit
import ctypes
from ctypes import wintypes

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

# input flags
ENABLE_PROCESSED_INPUT = 0x0001
ENABLE_LINE_INPUT = 0x0002
ENABLE_ECHO_INPUT = 0x0004
ENABLE_WINDOW_INPUT = 0x0008
ENABLE_MOUSE_INPUT = 0x0010
ENABLE_INSERT_MODE = 0x0020
ENABLE_QUICK_EDIT_MODE = 0x0040
ENABLE_EXTENDED_FLAGS = 0x0080

# output flags
ENABLE_PROCESSED_OUTPUT = 0x0001
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 # VT100 (Win 10)

def check_zero(result, func, args):
if not result:
err = ctypes.get_last_error()
if err:
raise ctypes.WinError(err)
return args

if not hasattr(wintypes, 'LPDWORD'): # PY2
wintypes.LPDWORD = ctypes.POINTER(wintypes.DWORD)

kernel32.GetConsoleMode.errcheck= check_zero
kernel32.GetConsoleMode.argtypes = (
wintypes.HANDLE, # _In_ hConsoleHandle
wintypes.LPDWORD,) # _Out_ lpMode

kernel32.SetConsoleMode.errcheck= check_zero
kernel32.SetConsoleMode.argtypes = (
wintypes.HANDLE, # _In_ hConsoleHandle
wintypes.DWORD,) # _Out_ lpMode

The following wraps the underlying WinAPI functions as get_console_mode and set_console_mode. I've limited the wrappers to operating on just the console's active input buffer or active output buffer, i.e. \\.\CONIN$ and \\.\CONOUT$. I think this is simpler than having to worry about file descriptors and handles. Notably sys.stdin and sys.stdout may be redirected elsewhere, as may also be the case for the C runtime's standard I/O FILE streams, file descriptors, and the Windows standard handles that you can get from GetStdHandle. In these cases you can still open CONIN$ and CONOUT$, as long as the process is attached to a console.

def get_console_mode(output=False):
'''Get the mode of the active console input or output
buffer. Note that if the process isn't attached to a
console, this function raises an EBADF IOError.
'''
device = r'\\.\CONOUT$' if output else r'\\.\CONIN$'
with open(device, 'r+') as con:
mode = wintypes.DWORD()
hCon = msvcrt.get_osfhandle(con.fileno())
kernel32.GetConsoleMode(hCon, ctypes.byref(mode))
return mode.value

def set_console_mode(mode, output=False):
'''Set the mode of the active console input or output
buffer. Note that if the process isn't attached to a
console, this function raises an EBADF IOError.
'''
device = r'\\.\CONOUT$' if output else r'\\.\CONIN$'
with open(device, 'r+') as con:
hCon = msvcrt.get_osfhandle(con.fileno())
kernel32.SetConsoleMode(hCon, mode)

update_console_mode combines the latter functions to let you pass in the flags you want to set and the mask of flags to modify. This includes flags to clear. It also allows restoring the previous mode by registering an atexit function.

def update_console_mode(flags, mask, output=False, restore=False):
'''Update a masked subset of the current mode of the active
console input or output buffer. Note that if the process
isn't attached to a console, this function raises an
EBADF IOError.
'''
current_mode = get_console_mode(output)
if current_mode & mask != flags & mask:
mode = current_mode & ~mask | flags & mask
set_console_mode(mode, output)
else:
restore = False
if restore:
atexit.register(set_console_mode, current_mode, output)

Example:

if __name__ == '__main__':
import os
import sys
import time

if sys.stderr is None:
os.close(2)
sys.stderr = open('stderr.txt', 'w', buffering=1)

print("%#06x, %#06x" % (get_console_mode(),
get_console_mode(output=True)))

flags = mask = ENABLE_EXTENDED_FLAGS | ENABLE_QUICK_EDIT_MODE
update_console_mode(flags, mask, restore=True)

print("%#06x, %#06x" % (get_console_mode(),
get_console_mode(output=True)))

time.sleep(10) # check console properties

How implement exit from console application using ctrl + x?

The CTRL+C and CTRL+BREAK key combinations receive special handling by console processes. By default, when a console window has the keyboard focus, CTRL+C or CTRL+BREAK is treated as a signal (SIGINT or SIGBREAK) and not as keyboard input. By default, these signals are passed to all console processes that are attached to the console. (Detached processes are not affected. See Creation of a Console.) The system creates a new thread in each client process to handle the event. The thread raises an exception if the process is being debugged. The debugger can handle the exception or continue with the exception unhandled.

CTRL+BREAK is always treated as a signal, but an application can change the default CTRL+C behavior in two ways that prevent the handler functions from being called:

  • The SetConsoleMode function can disable the ENABLE_PROCESSED_INPUT input mode for a console's input buffer, so CTRL+C is reported as keyboard input rather than as a signal.
  • When SetConsoleCtrlHandler is called with NULL and TRUE values for its parameters, the calling process ignores CTRL+C signals. Normal CTRL+C processing is restored by calling SetConsoleCtrlHandler with NULL and FALSE values. This attribute of ignoring or not ignoring CTRL+C signals is inherited by child processes, but it can be enabled or disabled by any process without affecting existing processes.

So we can do some basic things and disable CTRL+C and CTRL+Break first.

Console.TreatControlCAsInput = false;
Console.CancelKeyPress += delegate (object? sender, ConsoleCancelEventArgs e) {
e.Cancel = true;
};
Console.WriteLine("Hello, World!");
Console.ReadKey();

The next step is hook up and add ctrl+x

Console.TreatControlCAsInput = false;

Console.CancelKeyPress += delegate (object? sender, ConsoleCancelEventArgs e) {
e.Cancel = true;
};


ConsoleKeyInfo cki;

do
{
Console.WriteLine("Hello, World!");
//todo any work here
cki = Console.ReadKey(true);
} while (cki.Modifiers != ConsoleModifiers.Control && cki.Key != ConsoleKey.X);

Windows Console Application Getting Stuck (Needs Key Press)

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.

Is is possible to programmatically clear the console history?

Edit: Removed incorrect answer (I got confused about what you wanted to do) and added another (hopefully) better answer.

It might be possible to do this by freeing the current console using FreeConsole and then allocating a new console using AllocConsole. I'd assume that it wouldn't keep the command line history then.

In general, if you want to do things with the Console that's not supported by the .Net Framework, this MSDN page is a good place to look: Console Functions



Related Topics



Leave a reply



Submit