Заставить CreateProcess наследовать консоль вызывающего процесса - PullRequest
5 голосов
/ 04 декабря 2008

Когда я вызываю CreateProcess в Windows, новый процесс, похоже, не наследует консоль вызывающего процесса. Я сделал тестовую программу, которая запускает "ruby xtest", xtest - это скрипт, который пишет "привет" в стандартный вывод. Я запустил эту тестовую программу из Emacs, и ничего не получил. Я также попробовал следующий код, вызывающий GetStdHandle, но опять же, нет вывода. Затем я попытался передать CREATE_NEW_CONSOLE в dwCreationFlags в CreateProcess, который создал совершенно новое окно с выводом Ruby. Наконец я сделал простой форк / exec протестировать программу и скомпилировать ее с помощью Cygwin's GCC. Эта программа работала: выходные данные Ruby появились в Emacs, как и ожидалось. Я попытался расшифровать исходный код Cygwin в http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/spawn.cc?rev=1.268&content-type=text/x-cvsweb-markup&cvsroot=src, но не смог. Итак, как сделать так, чтобы новый процесс наследовал консоль родительского процесса так, чтобы выходные данные дочернего процесса отображались как положено?

STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.dwFlags |= STARTF_USESTDHANDLES;
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
if(!CreateProcess(0, "ruby xtest", 0, 0, 1, 0, 0, 0, &si, &pi)) die("CreateProcess");

Ответы [ 4 ]

5 голосов
/ 21 мая 2013

Я знаю, эта ветка довольно старая, однако я столкнулся с той же проблемой.

Так же, как и для TS, дескриптор консоли был унаследован и нормально работал под Cygwin, но не на консоли Windows. Вместо этого вывод на stdout не показывался и не сообщалось об ошибке. Унаследованные дескрипторы трубы работали до сих пор нормально.

Мне потребовалось некоторое время, чтобы выявить (теперь очевидную) проблему: CreateProcess () был вызван с CREATE_NO_WINDOW. Отбросив этот флаг, вывод на консоль в порядке. (Хотя, согласно коду TS, они никогда не устанавливают этот флаг в первую очередь.)

Надеюсь, это может быть полезно для людей, которые также наткнулись на эту тему, как я.

2 голосов
/ 25 января 2012

Согласно документации Microsoft, lpCommandLine (2. параметр):

Unicode-версия этой функции, CreateProcessW, может изменять содержимое этой строки. Следовательно, этот параметр не может быть указателем на постоянную память (например, константную переменную или литеральную строку). Если этот параметр является константной строкой, функция может вызвать нарушение прав доступа.

Когда я перестал использовать здесь константу, это сработало для меня. Мне не нужны были STARTF_USESTDHANDLES и GetStdHandle.

Этот код из консоли prg запускается и выводит другой exe консоли в той же консоли:

FillChar(SI, SizeOf(SI), 0);
SI.cb:=SizeOf(SI);
FillChar(PI, SizeOf(PI), 0);
if CreateProcess(nil, CmdLineVar, nil, nil, False, 0, nil, nil, SI, PI) then ...
1 голос
/ 13 марта 2009

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

Следующее работает для меня, и немного отличается от того, что он первоначально отправил. Сначала я подумал, что это не сработает, если вы не установите si.cb, но когда я прокомментировал это в моем, это все еще работало, так что ... YMMV.

   STARTUPINFO siStartInfo;
   ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
   siStartInfo.cb = sizeof(STARTUPINFO); 
   siStartInfo.hStdError = GetStdHandle(STD_OUTPUT_HANDLE); 
   siStartInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); 
   siStartInfo.hStdInput = g_hChildStd_IN_Rd;  // my outgoing pipe
   siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

// Create the child process. 

   bSuccess = CreateProcess(
      NULL,         
      szCmdline,    
      NULL,         
      NULL,         
      TRUE,         
      0,            
      NULL,         
      NULL,         
      &siStartInfo, 
      &piProcInfo); 
1 голос
/ 16 февраля 2009

Я сделал это, передав каналы для hStdInput, hStdOutput и hStdError и вручную перенаправив данные из каналов hStdOutput и hStdError на консоль.

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