当我在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");
答案 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)
我通过传递hStdInput
,hStdOutput
和hStdError
的管道并手动将hStdOutput
和hStdError
管道中的数据路由到控制台。
答案 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);