Ste*_*evo 6 c# console pinvoke stdout
我有一个有趣的(阅读:令人沮丧的)问题从C#WPF应用程序启动控制台应用程序并重定向其stdin和stdout.
它主要是启动和工作,但我似乎最终没有从stdout获取一些数据,一旦我开始重定向stdin.
我将用一个例子来澄清.如果我没有在STARTUPINFO结构中设置hStdInput,当我启动子进程时,我收到以下内容:
MongoDB shell version: 2.2.0
connecting to: test
local:PRIMARY>
Run Code Online (Sandbox Code Playgroud)
一旦我设置了hStdInput,我就得到这个:
MongoDB shell version: 2.2.0
connecting to: test
Run Code Online (Sandbox Code Playgroud)
我知道BackgroundWorker处理标准输出仍在运行,因为如果我在stdin上向进程发送一些内容,它会相应地做出响应.
use TestDB
switched to db TestDB
Run Code Online (Sandbox Code Playgroud)
所以,这就是我创建流程的方式:
_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);
}
Run Code Online (Sandbox Code Playgroud)
我在DoWork上有一个BackgroundWorker处理标准输出,它读取管道,如下所示:
success = ReadFile(
_hReadStdOut,
bufPtr,
1024,
&read,
IntPtr.Zero);
Run Code Online (Sandbox Code Playgroud)
我没有使用.Net Process类,因为在控制台应用程序发送换行符之前它没有从stdout获取数据,所以在这种情况下我也没有收到提示.
任何帮助都非常感谢.
干杯.
我怀疑以下内容可以解释您所观察到的情况:
hStdInput
子进程时,将使用附加到控制台的标准输入设备。子进程检测到标准输入是交互式控制台设备并写入提示。hStdInput
子进程时,它会检测到标准输入是管道,因此会忽略编写提示。毕竟,提示非交互式输入设备有什么意义呢?子进程将用于GetFileType(GetStdHandle(STD_INPUT_HANDLE))
检测连接到标准输入的设备类型。值FILE_TYPE_CHAR
表示控制台。当您将管道附加到标准输入时,标准输入文件类型将为FILE_TYPE_PIPE
.
我的结论是,一切都按设计和预期进行。