Почему моя командная строка зависает в Windows 10?

Я добавляю этот вопрос после целого дня борьбы с этой невероятно разочаровывающей функцией командной строки Windows 10, которая заставила меня подумать, что что-то не так с моим кодом консольного приложения. Надеюсь, это кому-нибудь поможет.

Проблема. Кажется, что мое консольное приложение перестало работать случайно. Что здесь происходит?

4 ответа

Решение

В итоге проблема стала новой функцией консоли windows 10. В конфигурации по умолчанию каждый раз, когда вы щелкаете по командному окну в Windows 10, он немедленно останавливает процесс приложения при попытке записи в консоль. Когда это происходит, командное окно переходит в режим "выбора".

Вы можете сказать, что это произошло, потому что к строке заголовка командного окна добавляется слово "Выбрать":

замороженное командное окно

Чтобы снова запустить вашу программу, вы должны нажать escape или щелкнуть где-нибудь еще.

Чтобы избавиться от этого странного поведения, вы можете отключить режим QuickEdit:

отключить режим QuickEdit

Что я хотел бы добавить здесь к ответу Шона Роуэна, так это то, что для того, чтобы он работал во всех окнах консоли, вы должны нажать "По умолчанию" вместо "Свойства" и внести свои изменения там, как описано в этом посте.

Я столкнулся с этой проблемой совсем недавно, когда один из пользователей (который настроил Quickedit в своей командной строке) использовал инструмент, разработанный мной на Java, и зависал при запуске из командной строки.

Наконец, проблема была решена путем перенаправления ведения журнала внутри пакетного сценария в файл, как показано ниже:

@echo off
...
java.exe -jar mytool.jar

необходимо обновить до

java.exe -jar mytool.jar > log.txt

Можно программно отключить надоедливый режим QuickEdit , импортировав файлы Windows.Kernel32.dllбиблиотеки и использование функций консольного APIGetStdHandle,GetConsoleMode, ичерез собственный интерфейс вашего языка (например, Java JNI, Python ctypes).

Питон с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. Если вы пишете программное обеспечение для запуска в нескольких операционных системах, обязательно обеспечьте защиту от ошибок.


Читать далее

С#:
Партия:
Другие вопросы по тегам