Разница между "консолью", "cmd.exe", "оболочкой"? - PullRequest
9 голосов
/ 26 февраля 2010

Я не совсем уверен в разнице между консолью (в "приложении консоли Windows"), cmd.exe, оболочкой.

  • Я знаю, что cmd.exe является автономным процессом при запуске, является ли cmd.exe == оболочкой? То есть оболочка - это просто процесс?
  • это консоль == cmd.exe?
  • MSDN сообщает ProcessStartInfo.UseShellExecute == True означает использование оболочки при запуске процесса, означает ли это, что процесс запускается так же, как я запускаю cmd.exe и запускаю программу из этой командной строки? Какой смысл делать это? У процесса, запущенного таким образом, есть своя консоль?

Заранее спасибо.

Ответы [ 2 ]

11 голосов
/ 26 февраля 2010
- MSDN сообщает ProcessStartInfo.UseShellExecute == True означает использование оболочки при запуске процесса, означает ли это, что процесс запускается так же, как я запускаю cmd.exe и запускаю программу из этой командной строки? Какой смысл делать это? У запущенного таким образом процесса есть своя консоль?

На самом деле это работает так:

  • если UseShellExecute имеет значение false, приложение будет запущено с использованием API CreateProcess ; этот API позволяет указать множество параметров запуска, среди которых есть возможность перенаправить stdin / stdout / stderr, но он будет запускать только исполняемые файлы. Если вы попытаетесь запустить файл (например, текстовый документ) с помощью CreateProcess, произойдет сбой, поскольку текстовые документы не являются исполняемыми файлами.
  • если UseShellExecute имеет значение true, процесс будет запущен с использованием ShellExecuteEx API; эта функция - та же функция, которую использует проводник Windows (« оболочка », по крайней мере, в терминологии Microsoft), когда вы дважды щелкаете файл в папке; его главное преимущество заключается в том, что он «знает», как запускать документы (открывать их с помощью связанных программ), он знает о папках оболочки… потому что он использует много возможностей оболочки. Однако у него есть несколько существенных недостатков: он довольно тяжелый по сравнению с обычным CreateProcess (потому что он должен выполнять много дополнительной работы), он не может открыть даже исполняемые файлы, если что-то не так с ассоциациями файлов / расширениями оболочки / ... и это не может перенаправить стандартный ввод / вывод / стандартный вывод. Не то чтобы теоретически это было бы невозможно: ведь ShellExecuteEx внутренне вызывает CreateProcess; проблема в том, что он не предоставляет эту функцию.

Итак, два метода создания процесса действительно совершенно разные; класс Process отлично справляется с их выравниванием, но функция, которая абсолютно не может быть воспроизведена с помощью функции ShellExecuteEx, - это перенаправление потоков ввода-вывода, поскольку она не доступна функцией ShellExecuteEx и может быть включена только при запуске процесса через CreateProcess.

Другой вопрос - использование консоли запущенной программой. Консоль выделяется / повторно используется внутри CreateProcess (фактически IIRC это связано с загрузчиком Windows PE, который проверяет необходимую подсистему в заголовке PE); правила создания / повторного использования консоли указаны здесь .

Если запущенное приложение является приложением с графическим интерфейсом, консоли вообще не создаются; с другой стороны, если консольное приложение запускается, оно повторно использует консоль своего родительского процесса, если только оно не указано в CreateProcess, и не вызывает флаг CREATE_NEW_CONSOLE. По умолчанию этот флаг не указывается, но я не уверен в том, что делает ShellExecuteEx с консольными приложениями, и у меня нет под рукой окна Windows для проверки. Я оставлю это в качестве упражнения для читателя. : P


Дополнительные ответы

Привет, Маттео, еще один вопрос. Если я создаю новый процесс как отдельный процесс, к которому не подключена консоль. Где сейчас находится процесс вывода? Куда идет вывод процесса? Отличается ли стандартный вывод процесса от выхода консоли?

Мне не понятно, что вы имеете в виду. Когда вы запускаете новый процесс с CreateProcess / ShellExecuteEx, консоль выделяется по мере необходимости, то есть, если исполняемый файл является исполняемым файлом консоли (как указано в заголовке PE), Windows предоставляет ему консоль (новую или родительскую в зависимости по указанным выше правилам); если исполняемый файл является приложением с графическим интерфейсом, для него не выделяется консоль.

IIRC, для приложений с графическим интерфейсом stdout / stdin / stderr - это просто битовые сегменты, т. Е. Они не указывают ни на что полезное, и весь ввод-вывод для них отбрасывается; кстати, ничто не мешает приложению с графическим интерфейсом выделить консоль и перенаправить на нее собственные потоки std *.

Имейте в виду, что консоль, потоки Windows std и потоки CRT std - это три разные вещи.Консоль - это просто интерфейс, который для консольных приложений по умолчанию удобно связан с потоками Windows std.

Потоки Windows std - это те, которые перенаправляются, когда вы указываете перенаправление stdin / stdout / stderr в CreateProcess;вы можете получить к ним дескрипторы с помощью функции GetStdHandle и перенаправить их с помощью SetStdHandle .

CRT stdin / stdout / stderr, наконец, еще одна абстракция, построенный библиотекой времени выполнения C;по умолчанию они привязаны к потокам Windows std.

Все это обычно работает без проблем, и вам даже не нужно беспокоиться о разнице между потоками Windows std и потоками CRT;однако, когда вы начинаете задумываться о перенаправлении потоков, это различие становится важным.

Если поток вывода stdout процесса отличается от вывода консоли, и Shell связывает эти 2 потока для нас.Будет ли выход процесса скопирован из process.stdout в console.output?это эффективно?

Оболочка не участвует в этом процессе, это ядро, которое выполняет сантехнику, следуя инструкциям, используемым в CreateProcess (или впоследствии измененным изнутри нового процесса с помощью других API).Для вашей производительности, с такой многоуровневой структурой, это единственный путь;и более того, копирующая часть (если это действительно копия, я подозреваю, что все дело просто в передаче указателей) - самая быстрая часть процесса, реальным узким местом является рисование / прокрутка окна консоли / и т.д.Фактически, если вы хотите запустить консольное приложение, позволяющее ему производить данные на полной скорости, вы обычно перенаправляете его стандартный вывод в файл или по каналу.

Большое спасибо.Маттео Италия.Вы хорошая проблема, совлер.: D

Спасибо.:)

3 голосов
/ 26 февраля 2010

Насколько я знаю:
Shell: интерфейс для операционной системы и, в конечном счете, для ядра. это включает explorer.exe и cmd.exe
Консоль: Вы создаете экземпляр консоли Win32. Это окно, которое выводит ваш Console.WriteLine
cmd.exe: интерпретатор командной строки Windows. он создает консоль Win32

Подробнее:
http://en.wikipedia.org/wiki/Win32_console [Консоль win32, консоль, которую вы используете, если вам не нужен графический интерфейс пользователя]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...