为远程进程的子进程捕获标准输出
Posted
技术标签:
【中文标题】为远程进程的子进程捕获标准输出【英文标题】:Capture stdout for a remote process' child process 【发布时间】:2018-03-06 07:13:43 【问题描述】:目前正在处理我需要为外部进程的子进程捕获标准输出/标准错误的情况。对于这种情况,我需要一个命名管道吗?
我目前尝试了以下方法:
SECURITY_ATTRIBUTES saAttr;
HANDLE hStdOutRd = NULL;
HANDLE hStdOutWr = NULL;
HANDLE hDupStdOutWr = NULL;
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
CreatePipe(&hStdOutRd, &hStdOutWr, &saAttr, 0) )
SetHandleInformation(hStdOutRd, HANDLE_FLAG_INHERIT, 0) )
HANDLE hExProc = OpenProcess(PROCESS_DUP_HANDLE, false, EXTERNAL_PROC);
DuplicateHandle(GetCurrentProcess(),
hStdOutWr,
hExProc,
&hDupStdOutWr,
0,
TRUE,
DUPLICATE_SAME_ACCESS);
// Child process for EXTERNAL_PROC executes and should inherit the duplicated handle
// Read from hStdOutRd
从管道读取时,它要么挂起,要么不返回任何内容。我假设这是一个匿名管道,只适用于父子进程而不是外部进程。我宁愿不使用命名管道,是否可以 DuplicateHandle() 管道从远程进程返回到我的进程,然后访问数据?如果是这样,那会是什么样子?
【问题讨论】:
这是特定于操作系统的。如果不提及操作系统,您的问题就不清楚了。也许你应该考虑像POCO 或Qt这样的框架 @BasileStarynkevitch 有问题的代码使用的是 Win32 API 函数,因此很明显它只能在 Windows 上运行。 命名管道与未命名或所谓的匿名管道相同。在你需要使用异步 io 来实现永不挂起。而CreatePipe
对这个目标不利。更好地使用CreateNamedPipe +CreateFile
。 DuplicateHandle
- 以及如何通知孩子重复值?
在 win7 之前 - CreatePipe
只需创建 2 个随机命名的命名管道。从 win7 开始 - 可能创建完全未命名的对。说CreatePipe
总是创建同步管道。但我们可以自己创建它,直接作为异步。可以只创建一个可继承的和一个 - 不。可以创建双工。真的 CreatePipe
非常受限的 api。
这非常相关 - 需要清楚地理解 - 不存在 2 种不同的管道类型(命名与未命名或随机命名) - 仅存在管道和所有。仅存在单个记录的 api 调用 CreatePipe
,它创建未命名的管道对 - 具有简单的接口但限制自定义(设置管道属性)。全部。操作是一样的。并可能直接(仅通过本机调用)创建具有任何所需属性的未命名对
【参考方案1】:
不,您不需要使用命名管道,匿名管道就可以了。 MSDN 提供了从子进程捕获输出的完整示例:
Creating a Child Process with Redirected Input and Output
【讨论】:
命名管道和匿名管道——绝对是同一个对象。和我认为的 msdn 示例非常糟糕。 OP 询问如何从他未启动的进程(通过OpenProcess()
获得的句柄)中捕获输出,我认为这不是(容易)可行的。
@zett42 我没有注意到OpenProcess()
部分。在这种情况下,您无法为自己未启动的进程重定向输出。
如果我自己使用 CreateProcess() 和 STARTUPINFOEX + PROC_THREAD_ATTRIBUTE_PARENT_PROCESS 启动进程会怎样?将句柄复制到我指定的远程父级并设置 bInheritHandle 是否可以让我访问孩子的标准输出?
@NotWarrenBuffet:无论您指定哪个进程作为子进程的父进程,当您直接调用CreateProcess()
时,您都可以通过STARTUPINFO/EX
结构为新子进程提供自己的STD(IN|OUT|ERR)
管道,就像我在回答中链接到的文章所展示的那样。你不需要复制任何东西。在dwFlags
字段中启用STARTF_USESTDHANDLES
标志,然后将管道的读取端分配给hStdOut
和hStdError
字段。以上是关于为远程进程的子进程捕获标准输出的主要内容,如果未能解决你的问题,请参考以下文章