为什么我的Windows 10命令提示符会冻结?

203
我在整整一天的努力中,终于解决了 Windows 10 命令提示符这个令人非常沮丧的问题。这个问题让我以为我的控制台应用程序代码有问题。希望这篇文章能够帮助到其他人。
问题:我的控制台应用程序似乎会随机停止运行。发生了什么?

5
你需要按下回车键以继续运行程序。 - wrivas
1
如果我在cmd窗口中点击,它到底会做什么? - phuclv
4个回答

380
问题最终是由于Windows 10控制台的新功能引起的。在默认配置下,当您单击Windows 10中的命令窗口时,它会立即停止应用程序进程,当它尝试写入控制台时。当这种情况发生时,命令窗口已进入“选择”模式。您可以通过标题栏前缀为“Select”来判断发生了什么:

frozen command window

为了使您的程序再次运行,您需要按下ESC键或单击其他位置。
要消除此奇怪的行为,您可以禁用快速编辑模式:

disable QuickEdit Mode


50
谢谢你,我的神啊!我已经处理了一年了,哈哈。另外,你可能需要取消选择该选项,关闭终端,然后重新打开它。至少对我来说是这样(否则它会自动重新启用)。 - user2875289
8
我有一个需要编译数小时的任务,但因为这个问题而总是卡住。很高兴你发布了解决方案! - Joel
2
尽管这个答案帮助禁用了点击时的冻结,但滚动侧边栏也会导致冻结。以前的行为是在滚动条被按住时冻结,并且当你释放滚动条时输出被打印出来。有什么办法可以恢复到旧的行为/取消冻结吗?Esc或Enter都不起作用。 - quimnuss
8
这是一个非常老的功能,用于加快复制和粘贴。只是Windows 10默认开始启用它。如何在PowerShell中禁用鼠标右键粘贴? - phuclv
4
“Feature not a bug” 是让用户烦恼的根源。 - tschwab
显示剩余13条评论

41
我想在 Shaun Rowan 的回答中补充的是,为了使其在所有控制台窗口中起作用,您必须单击“默认值”而不是“属性”,并在那里进行更改,如此帖子所述。

即使使用“Defaults”命令,程序仍然会冻结... - abc

3
我最近遇到了一个问题,其中一个用户(他的命令提示符上配置了Quickedit)在使用我开发的Java工具时,从命令提示符中运行该工具时会导致工具冻结。
最终解决问题的方法是将批处理脚本中的日志重定向到文件中,如下所示:
@echo off
...
java.exe -jar mytool.jar

需要��新为
java.exe -jar mytool.jar > log.txt

相关 https://superuser.com/questions/459609/what-does-it-do-exactly-if-i-click-in-the-window-of-cmd - rsinha
2
对于开发人员来说,这个线程可能很有趣,你可以使用SetConsoleMode(kernel32.dll)以编程方式禁用此行为。 - vgru

2

通过导入Windows的Kernel32.dll库并使用控制台API函数GetStdHandleGetConsoleModeSetConsoleMode,可以以编程方式禁用令人讨厌的QuickEdit模式。

使用Python的ctypes

简短(除了EXTENDED_FLAGS之外,禁用所有内容)。阅读SetConsoleMode文档以获取更多详细信息。

import ctypes

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

更长(禁用QUICK_EDIT_MODE而不改变其他设置)

import ctypes
import time
import threading

# Constants
STD_INPUT_HANDLE = -10

# Enum for ConsoleModes
class ConsoleModes(ctypes.c_uint):
    ENABLE_PROCESSED_INPUT = 0x1
    ENABLE_LINE_INPUT = 0x2
    ENABLE_ECHO_INPUT = 0x4
    ENABLE_WINDOW_INPUT = 0x8
    ENABLE_MOUSE_INPUT = 0x10
    ENABLE_INSERT_MODE = 0x20
    ENABLE_QUICK_EDIT_MODE = 0x40
    ENABLE_EXTENDED_FLAGS = 0x80
    ENABLE_AUTO_POSITION = 0x100

# Import kernel32.dll functions
kernel32 = ctypes.windll.kernel32
GetStdHandle = kernel32.GetStdHandle
GetConsoleMode = kernel32.GetConsoleMode
SetConsoleMode = kernel32.SetConsoleMode

def disable_quick_edit_mode():
    std_in = GetStdHandle(STD_INPUT_HANDLE)
    mode = ctypes.c_uint()
    if GetConsoleMode(std_in, ctypes.byref(mode)):
        if mode.value & ConsoleModes.ENABLE_QUICK_EDIT_MODE:
            mode.value ^= ConsoleModes.ENABLE_QUICK_EDIT_MODE
            SetConsoleMode(std_in, mode)

def print_numbers():
    i = 0
    while True:
        time.sleep(0.3)
        print(i)
        i += 1

def main():
    disable_quick_edit_mode()
    threading.Thread(target=print_numbers).start()

if __name__ == "__main__":
    main()

请记住,此代码仅在Windows上运行。如果您要编写可在多个操作系统上运行的软件,请确保防范错误。

阅读更多

C#:
批处理:

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接