使CreateProcess继承调用进程的控制台

时间:2008-12-04 12:02:07

标签: windows console createprocess

当我在Windows中调用CreateProcess时,新进程似乎不会继承调用进程的控制台。我制作了一个运行“ruby xtest”的测试程序,xtest是一个将“hello”写入标准输出的脚本。我从Emacs运行了这个测试程序,没有输出。我也尝试了以下代码调用GetStdHandle,但同样没有输出。然后我尝试将dwCreationFlags中的CREATE_NEW_CONSOLE传递给CreateProcess,后者用Ruby输出创建了一个全新的窗口。最后,我做了一个简单的fork / exec 测试程序并使用Cygwin的GCC编译它。这个程序工作:Ruby输出出现在Emacs中如预期的那样。我试图破译http://cygwin.com/cgi-bin/cvsweb.cgi/src/winsup/cygwin/spawn.cc?rev=1.268&content-type=text/x-cvsweb-markup&cvsroot=src中的Cygwin源代码,但失败了。那么,如何使新进程继承父进程的控制台,以便子进程的输出按预期显示?

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 个答案:

答案 0 :(得分:5)

我知道,这个线程相当陈旧,但是,我遇到了同样的问题。

就像TS一样,控制台句柄继承并在Cygwin下正常工作,但在Windows控制台上却没有。相反,stdout上的输出既未显示,也未报告任何错误。继承的管道句柄仍然正常。

我花了一些时间来确定(现在很明显的)问题:使用CREATE_NO_WINDOW调用CreateProcess()。删除此标志,控制台输出就可以了。 (尽管根据TS的代码,他们从未设置过这个标志。)

希望这可能对那些偶遇这个帖子的人有所帮助,比如我自己。

答案 1 :(得分:2)

根据Microsoft文档, lpCommandLine (2.参数):

  

此函数的Unicode版本CreateProcessW可以修改此字符串的内容。因此,此参数不能是只读内存的指针(例如const变量或文字字符串)。如果此参数是常量字符串,则该函数可能会导致访问冲突。

当我在这里停止使用常数时,它对我有效。我不需要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 ...

答案 2 :(得分:1)

我通过传递hStdInputhStdOutputhStdError的管道并手动将hStdOutputhStdError管道中的数据路由到控制台。

答案 3 :(得分:1)

不确定debeige是否曾经解决过这个问题,但是我需要同样的事情,但启动另一个线程来监听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);