7

当我在 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&中破译 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

4 回答 4

8

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

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

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

希望这可能对像我一样偶然发现此线程的人有所帮助。

于 2013-05-21T11:40:49.343 回答
2

根据微软文档,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 ...
于 2012-01-25T08:27:33.710 回答
1

我通过传入 、 和 的管道hStdInputhStdOutput手动hStdError将数据从hStdOutputhStdError管道路由到控制台来完成此操作。

于 2009-02-16T06:35:01.450 回答
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); 
于 2009-03-12T21:03:04.850 回答