如何从python启用Windows控制台QuickEdit模式?

时间:2016-05-28 14:18:51

标签: python windows console prompt

我想在运行python脚本时在控制台中强制使用QuickEdit Mode,然后在终止之前禁用它。有没有办法做到这一点?

3 个答案:

答案 0 :(得分:5)

您可以使用ctypes来呼叫GetConsoleModeSetConsoleMode

ctypes定义:

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

# 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

以下将基础WinAPI函数包装为get_console_modeset_console_mode。我已经将包装器限制为只在控制台的活动输入缓冲区或活动输出缓冲区上运行,即\\.\CONIN$\\.\CONOUT$。我认为这比担心文件描述符和句柄更简单。值得注意的是sys.stdinsys.stdout可能会重定向到其他地方,C运行时的标准I / O FILE流,文件描述符和Windows标准句柄也可能是这种情况。来自GetStdHandle。在这些情况下,只要流程附加到控制台,您仍然可以打开CONIN$CONOUT$

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结合后面的函数,让您传递要设置的flags和要修改的mask标志。这包括要清除的标志。它还允许通过注册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)

示例:

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_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

答案 1 :(得分:4)

适用于仅尝试为当前控制台禁用“快速编辑”和“插入”模式且无法找到简单解决方案的任何人:

import ctypes

kernel32 = ctypes.windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-10), 128)

答案 2 :(得分:2)

这可能对尝试在Windows中仅启用和禁用快速编辑模式而不禁用其他功能的任何人有用。

def quickedit(enabled=1): # This is a patch to the system that sometimes hangs
        import ctypes
        '''
        Enable or disable quick edit mode to prevent system hangs, sometimes when using remote desktop
        Param (Enabled)
        enabled = 1(default), enable quick edit mode in python console
        enabled = 0, disable quick edit mode in python console
        '''
        # -10 is input handle => STD_INPUT_HANDLE (DWORD) -10 | https://docs.microsoft.com/en-us/windows/console/getstdhandle
        # default = (0x4|0x80|0x20|0x2|0x10|0x1|0x40|0x200)
        # 0x40 is quick edit, #0x20 is insert mode
        # 0x8 is disabled by default
        # https://docs.microsoft.com/en-us/windows/console/setconsolemode
        kernel32 = ctypes.windll.kernel32
        if enabled:
            kernel32.SetConsoleMode(kernel32.GetStdHandle(-10), (0x4|0x80|0x20|0x2|0x10|0x1|0x40|0x100))
            print("Console Quick Edit Enabled")
        else:
            kernel32.SetConsoleMode(kernel32.GetStdHandle(-10), (0x4|0x80|0x20|0x2|0x10|0x1|0x00|0x100))
            print("Console Quick Edit Disabled")

quickedit(0) # Disable quick edit in terminal

只需禁用快速编辑的0x40标志