我有一个产生多个CreateProcess线程的应用程序,并且已成功将stdout和stderr输出重定向到每个文本文件。
但是,我发现了此功能,所有这些线程都继承了stdout / strderr句柄,而不仅仅是我希望它们继承的线程。因此,我开始了使用InitializeProcThreadAttributeList,UpdateProcThreadAttribute函数和EXTENDED_STARTUPINFO_PRESENT函数以及CreateProcess函数中的STARTUPINFOEX结构的旅程,以解决此问题,但我遇到了麻烦。
如果我在UpdateProcThreadAttribute过程中使用PROC_THREAD_ATTRIBUTE_HANDLE_LIST作为Attribute参数,则它期望lpValue参数是指向子进程将继承的句柄列表的指针。
对于列表,我尝试使用
TList<Cardinal>
并创建了一系列的红衣主教,但无法获得两种编译方法!
问题:如何创建和填充这样的列表?
其次,在此示例中,它使用的是kernel32.dll中的函数和过程,但它们也存在于Windows单元中(我使用的是Delphi 10.3),尽管定义不同:
例如,InitializeProcThreadAttributeList( nil, 1, 0, vAListSize );
由于使用nil参数,因此将不会使用Windows单元进行编译,因为实际和正式var参数的类型必须相同,但是在kernel32中使用一个则没有这样的问题
问题:我应该使用这些功能/过程的哪个版本?
谢谢。
如果有用,这是我的代码来实现所有这些:
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;
从您的文章它似乎是有一些声明InitializeProcThreadAttributeList
,UpdateProcThreadAttribute
并DeleteProcThreadAttributeList
在Windows
单位德尔福最新版本,但您的文章暗示,他们正在宣告错误。上面的代码可以正常工作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句