Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Ожидание завершения асинхронных подпроцессов в консольных приложениях на Delphi

Delphi , ОС и Железо , DOS и Консоль

Почему командный интерпретатор не возвращается после вызова WinExec?

Вопрос, который рассмотрен в данной статье, связан с использованием функции WinExec в консольном приложении на Delphi для вызова утилиты echo.exe из Cygwin с целью вывода цветного текста. Cygwin установлен в директории C:\cygwin, а его echo.exe находится по адресу C:\cygwin\bin\echo.exe. Автор выбрал WinExec вместо ShellExecute, так как последний запускает новый оболочку, что не требуется в данном случае.

Попытка №1

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

Попытка №2

Во второй попытке, как показано на следующем изображении, ясно, что WinExec уже завершил свою работу. Однако командный интерпретатор все еще не возвращается к приглашению. Автор был сбит с толку и обратился за комментариями. Пример кода с добавлением записи возвращаемого значения 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.

Альтернативный ответ и комментарии

Авторы комментариев предложили использовать функции WinAPI для работы с консолью вместо вызова Cygwin's echo, что выглядит более подходящим для Windows-приложения. Также было отмечено, что использование WinExec является устаревшим методом.

Подтвержденный ответ

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

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

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

Рекомендуемое решение

Используйте функцию CreateProcess для запуска подпроцесса, а затем дождитесь его завершения с помощью WaitForSingleObject. Это позволит вашей программе ожидать завершения асинхронного подпроцесса перед тем, как продолжить выполнение.

program WaitForProcess;
{$APPTYPE CONSOLE}
uses
  SysUtils, Windows;

var
  ProcessHandle: THandle;
  ExitCode: DWORD;
begin
  ProcessHandle := CreateProcess(nil, 'C:\cygwin\bin\echo.exe -e "\e[1;34mColored text.\e[0m"', nil, nil, FALSE, 0, nil, nil, nil, nil);
  if ProcessHandle <> 0 then
    WaitForSingleObject(ProcessHandle, INFINITE);
  GetExitCodeProcess(ProcessHandle, ExitCode);
  CloseHandle(ProcessHandle);
  Writeln('Process exited with code ', ExitCode);
  Readln;
end.

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

Создано по материалам из источника по ссылке.

Вопрос связан с проблемой, когда командный интерпретатор не возвращается к приглашению после вызова функции WinExec в консольном приложении на Delphi для запуска утилиты echo.exe из Cygwin с целью вывода цветного текста, и предлагается решение с использо


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




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


:: Главная :: DOS и Консоль ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-02-05 21:50:01/0.003593921661377/0