Почему оболочка CMD / Cygwin не возвращается после WinExec? - PullRequest
2 голосов
/ 27 марта 2012

Рассматриваемое консольное приложение Delphi пытается использовать WinExec для вызова Cygwin echo.exe для вывода с цветом. Cygwin устанавливается под C:\cygwin. Его echo.exe равно C:\cygwin\bin\echo.exe.

Причина выбора WinExec вместо ShellExecute в том, что ShellExecute создаст экземпляр новой оболочки и отобразит текст в этой новой оболочке.

То же самое происходит, когда я вызываю консольное приложение в оболочке CMD Windows.

Первая попытка

picture of the first attempt

Как показано на рисунке, оболочка не возвращается к приглашению. Хотя WinExec не заканчивает работу или не требует другой каретки.

program TestConsole;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows;

begin
  WinExec('C:\cygwin\bin\echo.exe -e "\e[1;34mColored text.\e[0m"', SW_NORMAL);
end.

Вторая попытка

picture of the second attempt

Как показано на рисунке, ясно, что WinExec уже закончил. Но оболочка все равно не возвращается к приглашению. Я запутался в причине. Не могли бы вы помочь прокомментировать? Любой комментарий будет оценен !!

program TestConsole;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows;

var
  I: Integer;
begin
  I := WinExec('C:\cygwin\bin\echo.exe -e "\e[1;34mColored text.\e[0m"', SW_NORMAL);
  Writeln(IntToStr(I));
end.

1 Ответ

4 голосов
/ 27 марта 2012

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

Когда вы вызываете WinExec, вы запускаете программу асинхронно . Эта функция не ожидает завершения команды echo, пока не вернет управление вашей программе, и ваша программа также не ожидает завершения выполнения команды. Поскольку оболочка ожидает только вашу программу, а не любые другие программы, которые ваша программа могла запустить, оболочка печатает свое приглашение, как только ваша программа завершает работу, что, очевидно, происходит раньше команде echo удается распечатать любой вывод.

Чтобы это исправить, вам нужно дождаться завершения команды echo, прежде чем вы позволите завершить свою собственную программу. WinExec не все, что вам делать, хотя. Это так же хорошо, так как он устарел около 17 лет. Вместо этого используйте CreateProcess. Он вернет дескриптор процесса, и вы можете передать этот дескриптор процесса в WaitForSingleObject, который будет блокироваться до завершения процесса.

...