如何将指针传递给UpdateProcThreadAttribute函数的句柄列表

问题描述 投票:1回答:1

我有一个产生多个CreateProcess线程的应用程序,并且我成功地将stdout和stderr输出重定向到每个文本文件。

但是,我发现了stdout / strderr句柄被所有此类线程继承的功能,而不仅仅是我希望它们被其继承的线程继承的功能。因此,我开始了使用InitializeProcThreadAttributeListUpdateProcThreadAttribute函数和CreateProcess]函数中的EXTENDED_STARTUPINFO_PRESENTSTARTUPINFOEX结构来解决此问题的旅程,但是我被卡住了。

如果我在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参数的类型必须相同

,但在kernel32中使用一个则没有这样的问题

问题:我应该使用这些功能/过程的哪个版本?

谢谢。

我有一个产生多个CreateProcess线程的应用程序,并且我成功地将stdout和stderr输出重定向到每个文本文件的文本文件。但是,我发现了......>

delphi winapi vcl kernel32
1个回答
3
投票

如果有用,这是我的代码来实现所有这些:

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;
© www.soinside.com 2019 - 2024. All rights reserved.