7

WindowsでCreateProcessを呼び出すと、新しいプロセスが呼び出し元のプロセスのコンソールを継承していないようです。「rubyxtest」を実行するテストプログラムを作成しました。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 の出力は表示されず、エラーも報告されませんでした。継承されたパイプ ハンドルは引き続き正常に機能しました。

(今では明らかな) 問題を特定するのに時間がかかりました: CreateProcess() が CREATE_NO_WINDOW で呼び出されました。このフラグを削除すると、コンソール出力は問題ありません。(ただし、TS の規定によると、最初からこのフラグを設定することはありませんでした。)

私のように、このスレッドに出くわした人々にとって、これが役立つことを願っています。

于 2013-05-21T11:40:49.343 に答える
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 ...
于 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 に答える