Interactive command history in session started with subprocess on Windows

Windows Terminal uses a modified build of conhost.exe that’s named openconsole.exe. I used procmon to monitor the registry keys it accesses at startup, and it appears the user’s console settings in “HKCU\Console” are never accessed, so openconsole.exe must use hard-coded defaults. You should still be able to use the console API to update the history settings dynamically. For example:

import ctypes
import collections
from ctypes import wintypes

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

HISTORY_NO_DUP_FLAG = 1

class CONSOLE_HISTORY_INFO(ctypes.Structure):
    _fields_ = (('cbSize', wintypes.UINT),
                ('HistoryBufferSize', wintypes.UINT),
                ('NumberOfHistoryBuffers', wintypes.UINT),
                ('dwFlags', wintypes.DWORD))

    def __init__(self, *args, **kwds):
        super().__init__(ctypes.sizeof(self), *args, **kwds)

ConsoleHistoryInfo = collections.namedtuple('ConsoleHistoryInfo', 
    'bufsize nbuf flags')

def get_console_history_info():
    info = CONSOLE_HISTORY_INFO()
    if not kernel32.GetConsoleHistoryInfo(ctypes.byref(info)):
        raise ctypes.WinError(ctypes.get_last_error())
    return ConsoleHistoryInfo(info.HistoryBufferSize, 
            info.NumberOfHistoryBuffers, info.dwFlags)

def set_console_history_info(bufsize=512, nbuf=32,
      flags=HISTORY_NO_DUP_FLAG):
    info = CONSOLE_HISTORY_INFO(bufsize, nbuf, flags)
    if not kernel32.SetConsoleHistoryInfo(ctypes.byref(info)):
        raise ctypes.WinError(ctypes.get_last_error())

Set the size to 512 commands with 32 buffers, and filter out duplicate commands:

>>> get_console_history_info()
ConsoleHistoryInfo(bufsize=50, nbuf=4, flags=0)

>>> set_console_history_info()
>>> get_console_history_info()
ConsoleHistoryInfo(bufsize=512, nbuf=32, flags=1)
3 Likes