我正在努力拼凑一个pinvoke'ing 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;
}
答案 0 :(得分:68)
这可能有点晚了,但仍然。
我在这里尝试了所有的例子,但没有人同时在32和64位模式下为我工作。最后,我被要求自己检查所有签名并创建相应的PInvoke例程。我想,其他人可能会觉得这很有帮助。
免责声明:该解决方案基于Matt Howells' answer。
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace JobManagement
{
public class Job : IDisposable
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr CreateJobObject(IntPtr a, string lpName);
[DllImport("kernel32.dll")]
static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);
private IntPtr handle;
private bool disposed;
public Job()
{
handle = CreateJobObject(IntPtr.Zero, null);
var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
{
LimitFlags = 0x2000
};
var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
BasicLimitInformation = info
};
int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error()));
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing) { }
Close();
disposed = true;
}
public void Close()
{
CloseHandle(handle);
handle = IntPtr.Zero;
}
public bool AddProcess(IntPtr processHandle)
{
return AssignProcessToJobObject(handle, processHandle);
}
public bool AddProcess(int processId)
{
return AddProcess(Process.GetProcessById(processId).Handle);
}
}
#region Helper classes
[StructLayout(LayoutKind.Sequential)]
struct IO_COUNTERS
{
public UInt64 ReadOperationCount;
public UInt64 WriteOperationCount;
public UInt64 OtherOperationCount;
public UInt64 ReadTransferCount;
public UInt64 WriteTransferCount;
public UInt64 OtherTransferCount;
}
[StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
public UInt32 LimitFlags;
public UIntPtr MinimumWorkingSetSize;
public UIntPtr MaximumWorkingSetSize;
public UInt32 ActiveProcessLimit;
public UIntPtr Affinity;
public UInt32 PriorityClass;
public UInt32 SchedulingClass;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public UInt32 nLength;
public IntPtr lpSecurityDescriptor;
public Int32 bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
public UIntPtr ProcessMemoryLimit;
public UIntPtr JobMemoryLimit;
public UIntPtr PeakProcessMemoryUsed;
public UIntPtr PeakJobMemoryUsed;
}
public enum JobObjectInfoType
{
AssociateCompletionPortInformation = 7,
BasicLimitInformation = 2,
BasicUIRestrictions = 4,
EndOfJobTimeInformation = 6,
ExtendedLimitInformation = 9,
SecurityLimitInformation = 5,
GroupInformation = 11
}
#endregion
}
答案 1 :(得分:6)
改进亚历山大的答案,这是一个使用SafeHandle
的版本。这是一个CriticalFinalizerObject
,使得处理句柄更加安全。 .NET API(例如Process
类)始终使用带有P / Invoke而不是SafeHandle
的{{1}}。
IntPtr
答案 2 :(得分:5)
总而言之,Alexander Yezutov提出的签名在x86和x64下都有效。当应该使用UIntPtr时,Matt Howells签名使用许多UInt32。我为CloseHandle使用了以下P / Invoke签名,似乎工作正常:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CloseHandle(IntPtr hObject);
以下内容必须添加到由Mas发布的app.manifest中:
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of all Windows versions that this application is designed to work with. Windows will automatically select the most compatible environment.-->
<!--The ID below indicates application support for Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--The ID below indicates application support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
</application>
最后,从Visual Studio启动时,这将不起作用(至少在Win 7下)。必须从Windows资源管理器启动父进程。
答案 3 :(得分:4)
有一篇帖子使用了您尝试使用的apis。 也许你可以从中获得一些见解。