如何使用JOB_OBJECT_BASIC_LIMIT_INFORMATION调用SetInformationJobObject?

时间:2015-09-16 14:25:27

标签: delphi winapi delphi-2010

我有一个Job API的基本翻译,如下所示:

type
  TJobObjectInfoClass = (
    JobObjectBasicLimitInformation = 2,
    JobObjectExtendedLimitInformation = 9
  );

  TJobObjectBasicLimitInformation = record
    PerProcessUserTimeLimit: TLargeInteger;
    PerJobUserTimeLimit: TLargeInteger;
    LimitFlags: DWORD;
    MinimumWorkingSetSize: DWORD;
    MaximumWorkingSetSize: DWORD;
    ActiveProcessLimit: DWORD;
    Affinity: DWORD;
    PriorityClass: DWORD;
    SchedulingClass: DWORD;
  end;

  TIOCounters = record
    ReadOperationCount: UInt64;
    WriteOperationCount: UInt64;
    OtherOperationCount: UInt64;
    ReadTransferCount: UInt64;
    WriteTransferCount: UInt64;
    OtherTransferCount: UInt64;
  end;

  TJobObjectExtendedLimitInformation = record
    BasicLimitInformation: TJobObjectBasicLimitInformation;
    IoInfo: TIOCounters;
    ProcessMemoryLimit: DWORD;
    JobMemoryLimit: DWORD;
    PeakProcessMemoryUsed: DWORD;
    PeakJobMemoryUsed: DWORD;
  end;

const
  CREATE_BREAKAWAY_FROM_JOB = $01000000;
  JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = $00002000;

function AssignProcessToJobObject(const hJob, hProcess: THandle): BOOL; stdcall;
external kernel32 name 'AssignProcessToJobObject';

function CreateJobObject(const lpJobAttributes: PSecurityAttributes;
  const lpName: PChar): THandle; stdcall;
external kernel32 name {$IFDEF UNICODE}'CreateJobObjectW'{$ELSE}'CreateJobObjectA'{$ENDIF};

function SetInformationJobObject(const hJob: THandle;
  const JobObjectInformationClass: TJobObjectInfoClass;
  const lpJobObjectInformation: Pointer;
  const cbJobObjectInformationLength: DWORD): BOOL; stdcall;
external kernel32 name 'SetInformationJobObject';

当我按如下方式使用它时,它可以正常工作:

Job := CreateJobObject(nil, nil);
if Job = 0 then
  RaiseLastOSError;

ZeroMemory(@JELI, SizeOf(JELI));
JELI.BasicLimitInformation.LimitFlags := JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
Win32Check(SetInformationJobObject(
  Job, JobObjectExtendedLimitInformation, @JELI, SizeOf(JELI))
);

由于我只设置了BasicLimitInformation,因此我希望能够用SetInformationJobObject来代替ZeroMemory(@JBLI, SizeOf(JBLI)); JBLI.LimitFlags := JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; Win32Check(SetInformationJobObject( Job, JobObjectBasicLimitInformation, @JBLI, SizeOf(JBLI)) );

{{1}}

MSDN上的文档没有给我任何迹象表明这不受支持。那么为什么它失败了代码87(“参数不正确”)?

我最好的猜测是我的记录与Windows期望的结构不完全匹配,这意味着某些位在错误的位置。然而,当它嵌入另一个时,它工作正常。在那里,它是第一个字段,因此填充不太可能是原因。

1 个答案:

答案 0 :(得分:0)

来自JOB_OBJECT_BASIC_LIMIT_INFORMATION的文档:

  

[JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE]需要使用JOBOBJECT_EXTENDED_LIMIT_INFORMATION结构。其BasicLimitInformation成员是JOBOBJECT_BASIC_LIMIT_INFORMATION结构。"

extended结构以basic结构开头,因此这两种结构至少部分兼容,这就是为什么你不能得到随机结果。

这应该给出正确的结果:

ZeroMemory(@JELI, SizeOf(JELI));
JELI.BasicLimitInformation.LimitFlags := JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
Win32Check(SetInformationJobObject(
  Job, JobObjectBasicLimitInformation, @JELI, SizeOf(JELI))
);