![](/img/trans.png)
[英]How to create create subprocess with a FILE* as its stdin, stdout or stderr?
[英]In Windows, how can one create a child process and capture its stdin, stdout, and stderr, without duplicating any inheritable handles?
这个问题至少有三个部分,所以请耐心等待:
1)CreateProcess有一个参数bInheritHandles,它使子进程继承父进程中的所有可继承句柄。 必须将此选项设置为TRUE,以允许父级在STARTUPINFO参数中为子级指定stdin,stdout和stderr句柄。
2)在Win32中,当同一个文件有多个句柄打开时,删除和重命名文件可能会失败。
3)Microsoft CRT的open()函数默认创建可继承的句柄。 此外,默认情况下创建的文件句柄会遇到上面的问题2。
这种神奇的组合会产生以下操作问题:库A调用open()并且不希望后续的重命名和删除失败。 在此过程中的另一个库B调用CreateProcess,并将bInheritHandles设置为TRUE(以捕获stdin / out / err),暂时创建重复句柄。 现在偶尔库A的文件操作失败了。 自然地,图书馆A和B由不同的人维护。 我也知道另一个使用open()并且遇到类似问题的库A'。
这篇kb文章讨论了一个相关的问题和解决方案。 但是它仍然依赖于在父进程中将bInheritHandles设置为TRUE来调用CreateProcess,因此它无法解决此问题。
我想知道其他人是否遇到过这个问题,是否有一个众所周知的解决方案?
上面的kb文章基本上暗示调用带有bInheritHandles设置为TRUE的CreateProcess很生,所以我倾向于修复库B,使它永远不会这样做。 我会这样做:
这是一个好策略还是有更好的解决方案? 您如何建议在步骤3中将欺骗手柄传递给中间过程? rundll +自定义入口点是在步骤1中设置中间过程的可靠方法吗?
如果您有权访问实际的文件句柄,则可以在调用CreateProcess()之前使用SetHandleInformation()删除HANDLE_FLAG_INHERIT标志。
您可以使用PROC_THREAD_ATTRIBUTE_HANDLE_LIST
扩展属性显式指定特定进程继承的句柄。
Raymond Chen的博客文章“以编程方式控制哪些句柄由Win32中的新进程继承”包括用于执行此操作的示例代码。
简短版本:
InitializeProcThreadAttributeList()创建属性列表
UpdateProcThreadAttribute指定要继承的句柄
lpAttributeList
成员在STARTUPINFOEX中设置
在调用CreateProcess时设置了EXTENDED_STARTUPINFO_PRESENT标志
需要Windows Vista,因此在最初询问此问题时可能没有解决OP问题,但是现在每个人都在使用Vista或更高版本,对吧? :-)
您可以使用ZwQuerySystemInformation(SystemHandleInformation,...)ntdll.dll函数查找您的进程拥有的所有句柄,然后按照Remy的建议在每个句柄上查找所有SetHandleInformation,以删除HANDLE_FLAG_INHERIT标志。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.