Почему мой рабочий процесс Windows на рабочем столе завершается немедленно без вывода stdout? - PullRequest
1 голос
/ 01 апреля 2020

У меня есть "hello world" Windows настольное приложение, источником которого является это официальное прохождение .

Когда я запускаю эту программу из Windows Подсистема для Linux, я получаю ожидаемое поведение: оболочка блокируется, ожидая завершения процесса, и приглашение оболочки появляется только после завершения процесса. Затем я могу проверить код завершения процесса (здесь установлен на 3, возвращая это из wWinMain):

jim@LAPTOP-SMUS1UJN:/mnt/c/Users/james/source/repos/DesktopApp/x64/Release$ ./DesktopApp.exe  # blocks until I close the window ...
jim@LAPTOP-SMUS1UJN:/mnt/c/Users/james/source/repos/DesktopApp/x64/Release$ echo $?
3

Однако , это не то поведение, которое я получаю при запуске программа из командной строки или из PowerShell. Здесь процесс начинается, но оболочка утверждает, что процесс немедленно завершился, и сразу же выдается новое приглашение! Но процесс явно не завершен, поскольку созданное им окно все еще существует, и я могу взаимодействовать с ним.

В обоих случаях (Windows Подсистема для Linux и PowerShell) стандартный вывод процесса не выводится на терминал. (Проверено с std::cout << "test", который ничего не печатает на терминал.)

Это как если бы оригинальный процесс породил процесс демона для запуска win32. Но я не думаю, что это именно то, что происходит, потому что Windows Подсистема для Linux как минимум блокирует до выхода.

Когда я создаю «консольное» приложение C ++ в Visual Studio, оно ведет себя, как и ожидалось. Странное поведение «ранний выход без вывода» происходит только для моей «настольной» программы win32.

Итак, почему командная строка или PowerShell утверждают, что процесс завершается немедленно? И где его стандартный вывод?

1 Ответ

4 голосов
/ 02 апреля 2020

Джонатан Поттер предоставил важные указания в комментарии к вопросу; разработать:

Любое данное Windows приложение подпадает под одну из этих двух взаимоисключающих категорий [1] :

  • GUI -подсистема приложений , таких как Notepad.exe:

    • Такие приложения обычно создают GUI windows, а иногда и вовсе без пользовательского интерфейса.

    • Из-за отсутствия связи с консолью они не могут записать в стандартный вывод (стандартный вывод) или потоки стандартной ошибки (стандартный вывод). [2]

  • Консоль-подсистема приложения , такие как findstr.exe:

    • Такие приложения либо создают консольное окно при вызове, либо запускаются в ранее существовавшем один, обычно тот, который создается оболочкой командной строки, такой как cmd.exe или PowerShell.

    • Они записывают выходные данные в стандартный вывод (стандартный вывод) и / или стандартный вывод ошибок (стандартный вывод ошибок) (stderr) потоки.

(на основе консоли) оболочки командной строки для Windows, например cmd.exe и PowerShell:

  • вызывает консольную подсистему приложения синхронно и сообщает свой код выхода : через псевдо-переменную окружения %ERRORLEVEL% в cmd.exe, и через переменную $LASTEXITCODE в PowerShell.

    • Кроме того, вывод stdout и / или stderr из такого приложения по умолчанию выводится на консоль, но его также можно перехватить, перенаправить или передать другому консоль-подсистема приложений по конвейеру.
  • вызывать GUI -систему приложений асинхронно по умолчанию, стиль запуска и забывания.

    • Таким образом, оболочка по умолчанию не ожидает завершения процесса приложения sh и не завершает его. сообщить свой код выхода.

    • Однако обе оболочки предлагают синхронный вызов, включая e xit-code report, на основе opt-in :

      • В cmd.exe, используйте start /WAIT ... как для синхронного выполнения, так и для кода выхода, отраженного в %ERRORLEVEL% впоследствии; см. документацию internal start .

      • В PowerShell используйте Start-Process -Wait ... для синхронного выполнения; чтобы также получить код завершения процесса, используйте $ps = Start-Process -Wait -PassThru ..., а затем проверьте $ps.ExitCode - см. документацию Start-Process командлета .


Напротив, POSIX-подобные оболочки из WSL (подсистема Windows для Linux) Например, bash:

  • вызывает оба консольные подсистемы и GUI подсистемные приложения синхронно по умолчанию и впоследствии отображают код завершения любого типа приложения во встроенной переменной $?.

  • Для выбора асинхронный вызов, используйте postpositional & для выполнения вызова из фона job ; например, (Notepad.exe &)

    • Примечание: (...) подавляет сообщение о состоянии управления работой оболочки, которое запускается & (действует в bash, zsh и dash, но не ksh); подробности см. в этом ответе .

[1] Подсистемы GUI и консоли являются соответствующими для исполняемых файлов. предназначен для непосредственного управления конечными пользователями. Существуют другие подсистемы, как описано в этой справке topi c в формате PE (формат исполняемых файлов в Windows). Подсказка Джеймсу (ОП) для предоставления ссылки.

[2] Хотя GUI -подсистемные приложения могут явно создавать консоль по требованию, такая консоль независима консоли вызывающей консоли-подсистемы. Возможно даже присоединить к ранее существовавшую консоль вызывающей консоли-подсистемы, но вызывающая сторона не будет знать об этом и, следовательно, не сможет захватывать, перенаправлять или передавать любые записанные выходные данные. к этой консоли с помощью GUI -подсистемного приложения.

...