我有一个产生多个CreateProcess线程的应用程序,并且我成功地将stdout和stderr输出重定向到每个文本文件。
但是,我发现了stdout / strderr句柄被所有此类线程继承的功能,而不仅仅是我希望它们被其继承的线程继承的功能。因此,我开始了使用InitializeProcThreadAttributeList,UpdateProcThreadAttribute函数和CreateProcess]函数中的EXTENDED_STARTUPINFO_PRESENT和STARTUPINFOEX结构来解决此问题的旅程,但是我被卡住了。
如果我在UpdateProcThreadAttribute
过程中将PROC_THREAD_ATTRIBUTE_HANDLE_LIST用作Attribute参数,它期望lpValue参数是指向要由子进程继承的句柄列表的指针 。对于我尝试使用的列表
TList<Cardinal>
并且还创建了一组红衣主教,但无法获得两种编译方法!
问题:如何创建和填充这样的列表?
其次,in this example使用的是kernel32.dll中的函数和过程,但它们也存在于Windows单元中(我使用的是Delphi 10.3),尽管定义不同:
例如,由于使用nil参数,InitializeProcThreadAttributeList( nil, 1, 0, vAListSize );
不会使用Windows单元进行编译,因为实际和形式上的var参数的类型必须相同
问题:我应该使用这些功能/过程的哪个版本?
谢谢。
我有一个产生多个CreateProcess线程的应用程序,并且我成功地将stdout和stderr输出重定向到每个文本文件的文本文件。但是,我发现了......>
如果有用,这是我的代码来实现所有这些:
type
TStartupInfoEx = record
StartupInfo: TStartupInfo;
lpAttributeList: Pointer;
end;
const
PROC_THREAD_ATTRIBUTE_HANDLE_LIST = $00020002;
function InitializeProcThreadAttributeList(
lpAttributeList: Pointer;
dwAttributeCount: DWORD;
dwFlags: DWORD;
var lpSize: SIZE_T
): BOOL; stdcall; external kernel32;
function UpdateProcThreadAttribute(
lpAttributeList: Pointer;
dwFlags: DWORD;
Attribute: DWORD_PTR;
lpValue: Pointer;
cbSize: SIZE_T;
lpPreviousValue: PPointer;
lpReturnSize: PSIZE_T
): BOOL; stdcall; external kernel32;
function DeleteProcThreadAttributeList(
lpAttributeList: Pointer
): BOOL; stdcall; external kernel32;
function CreateProcessWithInheritedHandles(
lpApplicationName: LPCWSTR;
lpCommandLine: LPWSTR;
lpProcessAttributes,
lpThreadAttributes: PSecurityAttributes;
const Handles: array of THandle;
dwCreationFlags: DWORD;
lpEnvironment: Pointer;
lpCurrentDirectory: LPCWSTR;
const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation
): Boolean;
var
i: Integer;
StartupInfoEx: TStartupInfoEx;
size: SIZE_T;
begin
Assert(Length(Handles)>0);
StartupInfoEx.StartupInfo := lpStartupInfo;
StartupInfoEx.StartupInfo.cb := SizeOf(StartupInfoEx);
StartupInfoEx.lpAttributeList := nil;
Win32Check(not InitializeProcThreadAttributeList(nil, 1, 0, size) and (GetLastError=ERROR_INSUFFICIENT_BUFFER));
GetMem(StartupInfoEx.lpAttributeList, size);
try
Win32Check(InitializeProcThreadAttributeList(StartupInfoEx.lpAttributeList, 1, 0, size));
try
Win32Check(UpdateProcThreadAttribute(
StartupInfoEx.lpAttributeList,
0,
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
@Handles[0],
Length(Handles) * SizeOf(Handles[0]),
nil,
nil
));
for i := 0 to High(Handles) do begin
Win32Check(SetHandleInformation(Handles[i], HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT));
end;
Result := CreateProcess(
lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
True,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
StartupInfoEx.StartupInfo,
lpProcessInformation
);
finally
DeleteProcThreadAttributeList(StartupInfoEx.lpAttributeList);
end;
finally
FreeMem(StartupInfoEx.lpAttributeList);
end;
end;