如何将指向句柄列表的指针传递给 UpdateProcThreadAttribute 函数
How to pass a pointer to a list of handles to the UpdateProcThreadAttribute function
我有一个生成多个 CreateProcess 线程的应用程序,我成功地将每个线程的 stdout 和 stderr 输出重定向到文本文件。
但是,我发现了 stdout/strderr 句柄被所有此类线程继承的特性,而不仅仅是我希望它们被继承的线程。所以我开始了使用 InitializeProcThreadAttributeList、UpdateProcThreadAttribute 函数和 EXTENDED_STARTUPINFO_PRESENT[=44= 的旅程] 和 STARTUPINFOEX 函数中的 CreateProcess 结构来解决这个问题,但我被卡住了。
如果我在 UpdateProcThreadAttribute 过程中使用 PROC_THREAD_ATTRIBUTE_HANDLE_LIST 作为 Attribute 参数它期望 lpValue 参数是指向子进程继承的句柄列表的指针。
对于列表,我尝试使用
TList<Cardinal>
并且还创建了一个 Cardinals 数组,但无法获得任何一种编译方法!
问题:如何创建和填充这样的列表?
其次,in this example 它正在使用 kernel32.dll 中的函数和过程,但它们也存在于 Windows 单元中(我使用的是 Delphi 10.3)尽管定义不同:
例如,由于 nil 参数,InitializeProcThreadAttributeList( nil, 1, 0, vAListSize );
不会使用 Windows 单元进行编译,因为 实际和形式 var 参数的类型必须相同 但我使用 kernel32
中的那个没有这样的问题
问题:我应该使用 functions/procedures 中的哪个版本?
谢谢。
如果它有用,这里是我实现所有这些的代码:
type
TStartupInfoEx = record
StartupInfo: TStartupInfo;
lpAttributeList: Pointer;
end;
const
PROC_THREAD_ATTRIBUTE_HANDLE_LIST = [=10=]020002;
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;
从你的 post 来看,最新版本的 Windows
单元中似乎有一些 InitializeProcThreadAttributeList
、UpdateProcThreadAttribute
和 DeleteProcThreadAttributeList
的声明Delphi,但您的 post 暗示它们的声明不正确。已知以上代码可以正常工作。
我有一个生成多个 CreateProcess 线程的应用程序,我成功地将每个线程的 stdout 和 stderr 输出重定向到文本文件。
但是,我发现了 stdout/strderr 句柄被所有此类线程继承的特性,而不仅仅是我希望它们被继承的线程。所以我开始了使用 InitializeProcThreadAttributeList、UpdateProcThreadAttribute 函数和 EXTENDED_STARTUPINFO_PRESENT[=44= 的旅程] 和 STARTUPINFOEX 函数中的 CreateProcess 结构来解决这个问题,但我被卡住了。
如果我在 UpdateProcThreadAttribute 过程中使用 PROC_THREAD_ATTRIBUTE_HANDLE_LIST 作为 Attribute 参数它期望 lpValue 参数是指向子进程继承的句柄列表的指针。
对于列表,我尝试使用
TList<Cardinal>
并且还创建了一个 Cardinals 数组,但无法获得任何一种编译方法!
问题:如何创建和填充这样的列表?
其次,in this example 它正在使用 kernel32.dll 中的函数和过程,但它们也存在于 Windows 单元中(我使用的是 Delphi 10.3)尽管定义不同:
例如,由于 nil 参数,InitializeProcThreadAttributeList( nil, 1, 0, vAListSize );
不会使用 Windows 单元进行编译,因为 实际和形式 var 参数的类型必须相同 但我使用 kernel32
问题:我应该使用 functions/procedures 中的哪个版本?
谢谢。
如果它有用,这里是我实现所有这些的代码:
type
TStartupInfoEx = record
StartupInfo: TStartupInfo;
lpAttributeList: Pointer;
end;
const
PROC_THREAD_ATTRIBUTE_HANDLE_LIST = [=10=]020002;
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;
从你的 post 来看,最新版本的 Windows
单元中似乎有一些 InitializeProcThreadAttributeList
、UpdateProcThreadAttribute
和 DeleteProcThreadAttributeList
的声明Delphi,但您的 post 暗示它们的声明不正确。已知以上代码可以正常工作。