6

C# WPF アプリからコンソール アプリケーションを起動し、その stdin と stdout をリダイレクトするという興味深い (読む: イライラする) 問題があります。

それはほとんど稼働していますが、標準入力のリダイレクトを開始するとすぐに、標準出力から一部のデータを取得できなくなったようです。

例を挙げて説明します。STARTUPINFO 構造体で hStdInput を設定しない場合、子プロセスを開始すると、次のメッセージが表示されます。

MongoDB shell version: 2.2.0
connecting to: test
local:PRIMARY>

ただし、hStdInput を設定すると、次のようになります。

MongoDB shell version: 2.2.0
connecting to: test

stdin でプロセスに何かを送信すると、それに応じて応答するため、BackgroundWorker 処理 stdout がまだ機能していることはわかっています。

use TestDB
switched to db TestDB

だから、これは私がプロセスを作成する方法です:

_processInfo = new ProcessInfo();

bool ok = false;

SECURITY_ATTRIBUTES sattr = new SECURITY_ATTRIBUTES();
sattr.bInheritHandle = 1;
unsafe
{
    sattr.lpSecurityDescriptor = null;
}
sattr.nLength = Marshal.SizeOf(sattr);

IntPtr hWrite;
ok = CreatePipe(out _hReadStdOut, out hWrite, ref sattr, 0);
ok = SetHandleInformation(_hReadStdOut, HANDLE_FLAGS.INHERIT, 0);
IntPtr hRead;
ok = CreatePipe(out hRead, out _hWriteStdIn, ref sattr, 0);
ok = SetHandleInformation(_hWriteStdIn, HANDLE_FLAGS.INHERIT, 0);

var startInfo = new StartupInfo
{
    dwFlags = 0x0001 | 0x0100,
    wShowWindow = 0,
    hStdOutput = hWrite,
    hStdError = hWrite,
    hStdInput = hRead // If this is IntPtr.Zero, I get everything from stdout
};

SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES();
pSec.nLength = Marshal.SizeOf(pSec);
SECURITY_ATTRIBUTES tSec = new SECURITY_ATTRIBUTES();
tSec.nLength = Marshal.SizeOf(tSec);

unsafe
{
    ok = CreateProcess(
        null,
        pathToExeAndArgs,
        ref pSec,
        ref tSec,
        true,
        0,
        IntPtr.Zero,
        null,
        ref startInfo,
        out _processInfo);
}

次のようにパイプを読み取る DoWork の標準出力を処理する BackgroundWorker があります。

success = ReadFile(
    _hReadStdOut,
    bufPtr,
    1024,
    &read,
    IntPtr.Zero);

コンソール アプリケーションが改行を送信するまで stdout からデータを取得しなかったため、.Net Process クラスを使用していないため、その場合もプロンプトが返されませんでした。

これに関するヘルプは大歓迎です。

乾杯。

4

1 に答える 1

1

私はあなたが観察したことを次のように説明していると思います:

  • 子プロセスを定義しない場合hStdInput、コンソールに接続された標準入力デバイスが使用されます。子プロセスは、標準入力が対話型コンソール デバイスであることを検出し、プロンプトを書き込みます。
  • 定義するhStdInputと、子プロセスは標準入力がパイプであることを検出し、プロンプトの書き込みを無視します。結局のところ、非対話型入力デバイスにプロンプ​​トを表示する意味は何ですか?

子プロセスはGetFileType(GetStdHandle(STD_INPUT_HANDLE))、標準入力に接続されているデバイスのタイプを検出するために使用します。の値はFILE_TYPE_CHARコンソールを示します。標準入力にパイプを接続すると、標準入力ファイルのタイプはFILE_TYPE_PIPE.

私の結論は、すべてが設計および意図したとおりに機能しているということです。

于 2012-12-08T16:06:14.560 に答える