.net 中 CreateJobObject/SetInformationJobObject pinvoke 的工作示例?
我正在努力整理一个 pinvoke CreateJobObject 和 SetInformationJobObject 的工作示例。通过各种谷歌搜索(包括俄语和中文帖子!),我拼凑了以下代码。我认为 JOBOBJECT_BASIC_LIMIT_INFORMATION 的定义根据平台(32/64 位)而变化。 CreateJobObject/AssignProcessToJobObject似乎可以工作。 SetInformationJobObject 失败 - 错误为 24 或 87。
Process myProcess // POPULATED SOMEWHERE ELSE
// Create Job & assign this process and another process to the job
IntPtr jobHandle = CreateJobObject( null , null );
AssignProcessToJobObject( jobHandle , myProcess.Handle );
AssignProcessToJobObject( jobHandle , Process.GetCurrentProcess().Handle );
// Ensure that killing one process kills the others
JOBOBJECT_BASIC_LIMIT_INFORMATION limits = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
limits.LimitFlags = (short)LimitFlags.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
IntPtr pointerToJobLimitInfo = Marshal.AllocHGlobal( Marshal.SizeOf( limits ) );
Marshal.StructureToPtr( limits , pointerToJobLimitInfo , false );
SetInformationJobObject( job , JOBOBJECTINFOCLASS.JobObjectBasicLimitInformation , pionterToJobLimitInfo , ( uint )Marshal.SizeOf( limits ) )
...
[DllImport( "kernel32.dll" , EntryPoint = "CreateJobObjectW" , CharSet = CharSet.Unicode )]
public static extern IntPtr CreateJobObject( SecurityAttributes JobAttributes , string lpName );
public class SecurityAttributes
{
public int nLength; //Useless field = 0
public IntPtr pSecurityDescriptor; //хз))
public bool bInheritHandle; //Возможность наследования
public SecurityAttributes()
{
this.bInheritHandle = true;
this.nLength = 0;
this.pSecurityDescriptor = IntPtr.Zero;
}
}
[DllImport( "kernel32.dll" )]
static extern bool SetInformationJobObject( IntPtr hJob , JOBOBJECTINFOCLASS JobObjectInfoClass , IntPtr lpJobObjectInfo , uint cbJobObjectInfoLength );
public enum JOBOBJECTINFOCLASS
{
JobObjectAssociateCompletionPortInformation = 7 ,
JobObjectBasicLimitInformation = 2 ,
JobObjectBasicUIRestrictions = 4 ,
JobObjectEndOfJobTimeInformation = 6 ,
JobObjectExtendedLimitInformation = 9 ,
JobObjectSecurityLimitInformation = 5
}
[StructLayout( LayoutKind.Sequential )]
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
public Int16 LimitFlags;
public UIntPtr MinimumWorkingSetSize;
public UIntPtr MaximumWorkingSetSize;
public Int16 ActiveProcessLimit;
public Int64 Affinity;
public Int16 PriorityClass;
public Int16 SchedulingClass;
}
public enum LimitFlags
{
JOB_OBJECT_LIMIT_ACTIVE_PROCESS = 0x00000008 ,
JOB_OBJECT_LIMIT_AFFINITY = 0x00000010 ,
JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800 ,
JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION = 0x00000400 ,
JOB_OBJECT_LIMIT_JOB_MEMORY = 0x00000200 ,
JOB_OBJECT_LIMIT_JOB_TIME = 0x00000004 ,
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x00002000 ,
JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME = 0x00000040 ,
JOB_OBJECT_LIMIT_PRIORITY_CLASS = 0x00000020 ,
JOB_OBJECT_LIMIT_PROCESS_MEMORY = 0x00000100 ,
JOB_OBJECT_LIMIT_PROCESS_TIME = 0x00000002 ,
JOB_OBJECT_LIMIT_SCHEDULING_CLASS = 0x00000080 ,
JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK = 0x00001000 ,
JOB_OBJECT_LIMIT_WORKINGSET = 0x00000001
}
[DllImport( "kernel32.dll" )]
[return: MarshalAs( UnmanagedType.Bool )]
static extern bool AssignProcessToJobObject( IntPtr hJob , IntPtr hProcess );
[StructLayout( LayoutKind.Sequential )]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
I'm struggling to put together a working example of pinvoke'ing CreateJobObject and SetInformationJobObject. Through various google searches (including Russian and Chinese posts!) I've cobbled together the following code. I think the definition of JOBOBJECT_BASIC_LIMIT_INFORMATION changes based on platform (32/64-bit). The CreateJobObject/AssignProcessToJobObject seems to work. SetInformationJobObject fails - either with error 24 or 87.
Process myProcess // POPULATED SOMEWHERE ELSE
// Create Job & assign this process and another process to the job
IntPtr jobHandle = CreateJobObject( null , null );
AssignProcessToJobObject( jobHandle , myProcess.Handle );
AssignProcessToJobObject( jobHandle , Process.GetCurrentProcess().Handle );
// Ensure that killing one process kills the others
JOBOBJECT_BASIC_LIMIT_INFORMATION limits = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
limits.LimitFlags = (short)LimitFlags.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
IntPtr pointerToJobLimitInfo = Marshal.AllocHGlobal( Marshal.SizeOf( limits ) );
Marshal.StructureToPtr( limits , pointerToJobLimitInfo , false );
SetInformationJobObject( job , JOBOBJECTINFOCLASS.JobObjectBasicLimitInformation , pionterToJobLimitInfo , ( uint )Marshal.SizeOf( limits ) )
...
[DllImport( "kernel32.dll" , EntryPoint = "CreateJobObjectW" , CharSet = CharSet.Unicode )]
public static extern IntPtr CreateJobObject( SecurityAttributes JobAttributes , string lpName );
public class SecurityAttributes
{
public int nLength; //Useless field = 0
public IntPtr pSecurityDescriptor; //хз))
public bool bInheritHandle; //Возможность наследования
public SecurityAttributes()
{
this.bInheritHandle = true;
this.nLength = 0;
this.pSecurityDescriptor = IntPtr.Zero;
}
}
[DllImport( "kernel32.dll" )]
static extern bool SetInformationJobObject( IntPtr hJob , JOBOBJECTINFOCLASS JobObjectInfoClass , IntPtr lpJobObjectInfo , uint cbJobObjectInfoLength );
public enum JOBOBJECTINFOCLASS
{
JobObjectAssociateCompletionPortInformation = 7 ,
JobObjectBasicLimitInformation = 2 ,
JobObjectBasicUIRestrictions = 4 ,
JobObjectEndOfJobTimeInformation = 6 ,
JobObjectExtendedLimitInformation = 9 ,
JobObjectSecurityLimitInformation = 5
}
[StructLayout( LayoutKind.Sequential )]
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
public Int16 LimitFlags;
public UIntPtr MinimumWorkingSetSize;
public UIntPtr MaximumWorkingSetSize;
public Int16 ActiveProcessLimit;
public Int64 Affinity;
public Int16 PriorityClass;
public Int16 SchedulingClass;
}
public enum LimitFlags
{
JOB_OBJECT_LIMIT_ACTIVE_PROCESS = 0x00000008 ,
JOB_OBJECT_LIMIT_AFFINITY = 0x00000010 ,
JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800 ,
JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION = 0x00000400 ,
JOB_OBJECT_LIMIT_JOB_MEMORY = 0x00000200 ,
JOB_OBJECT_LIMIT_JOB_TIME = 0x00000004 ,
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x00002000 ,
JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME = 0x00000040 ,
JOB_OBJECT_LIMIT_PRIORITY_CLASS = 0x00000020 ,
JOB_OBJECT_LIMIT_PROCESS_MEMORY = 0x00000100 ,
JOB_OBJECT_LIMIT_PROCESS_TIME = 0x00000002 ,
JOB_OBJECT_LIMIT_SCHEDULING_CLASS = 0x00000080 ,
JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK = 0x00001000 ,
JOB_OBJECT_LIMIT_WORKINGSET = 0x00000001
}
[DllImport( "kernel32.dll" )]
[return: MarshalAs( UnmanagedType.Bool )]
static extern bool AssignProcessToJobObject( IntPtr hJob , IntPtr hProcess );
[StructLayout( LayoutKind.Sequential )]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这可能有点晚了,但仍然如此。
我尝试了这里的所有示例,但没有人同时在 32 位和 64 位模式下为我工作。最后,我需要亲自检查所有签名并创建相应的 PInvoke 例程。我想,其他人可能会发现这很有帮助。
免责声明:该解决方案基于Matt Howells 的回答。
This can be little bit late, but still.
I tried all of the examples here, but no one was working for me in 32 and 64 bit mode simultaneously. Finally, I was required to examine all the signatures myself and create corresponding PInvoke routines. I think, somebody else could find this helpful.
Disclaimer: the solution is based on Matt Howells' answer.
改进亚历山大的答案,这里有一个使用
SafeHandle
的版本。这是一个CriticalFinalizerObject
,它使句柄的使用更加安全。 .NET API(例如Process
类)始终将SafeHandle
与 P/Invoke 结合使用,而不是IntPtr
。Improving on Alexander's answer, here's a version that uses a
SafeHandle
. This is aCriticalFinalizerObject
that makes working with handles much safer. .NET APIs (such as theProcess
class) always useSafeHandle
s with P/Invoke instead ofIntPtr
s.总而言之,Alexander Yezutov 提出的签名可以在 x86 和 x64 下工作。当应使用 UIntPtr 时,Matt Howells 签名使用许多 UInt32。我对 CloseHandle 使用了以下 P/Invoke 签名,它似乎工作正常:
必须将以下内容添加到 Mas 发布的 app.manifest 中:
最后,当从 Visual Studio 启动时,这将不起作用(至少在 Win 7 下)。父进程必须从 Windows 资源管理器启动。
To summarize, the signatures posed by Alexander Yezutov work under both x86 and x64. Matt Howells signatures use a number of UInt32's when UIntPtr should be used instead. I used the following P/Invoke signature for the CloseHandle which seems to work fine:
The following must be added to the app.manifest as posted by Mas:
and lastly, this won't work (at least under Win 7) when launched from Visual Studio. The parent process must be started from Windows Explorer.
有一篇文章使用了您正在尝试使用的 api。
也许您可以从中获得一些见解。
当父进程被终止时终止子进程
There is a post that uses apis that you are trying to use.
Perhaps you can get some insight from there.
Kill child process when parent process is killed