ProjectArcade
156 строк · 4.5 Кб
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Runtime.InteropServices;
6using System.Diagnostics;
7
8namespace EmulatorLauncher.Common
9{
10public class Job : IDisposable
11{
12public static Job Current { get { if (_job == null) _job = new Job(); return _job; } }
13private static Job _job;
14
15
16[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
17static extern IntPtr CreateJobObject(IntPtr a, string lpName);
18
19[DllImport("kernel32.dll")]
20static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength);
21
22[DllImport("kernel32.dll", SetLastError = true)]
23static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
24
25[DllImport("kernel32.dll", SetLastError = true)]
26[return: MarshalAs(UnmanagedType.Bool)]
27static extern bool CloseHandle(IntPtr hObject);
28
29private IntPtr handle;
30private bool disposed;
31
32public Job()
33{
34handle = CreateJobObject(IntPtr.Zero, null);
35
36var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
37{
38LimitFlags = 0x2000 // JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
39};
40
41var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
42{
43BasicLimitInformation = info
44};
45
46int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
47IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
48Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
49
50if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
51throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error()));
52}
53
54public void Dispose()
55{
56Dispose(true);
57GC.SuppressFinalize(this);
58}
59
60private void Dispose(bool disposing)
61{
62if (disposed)
63return;
64
65if (disposing) { }
66
67Close();
68disposed = true;
69}
70
71public void Close()
72{
73CloseHandle(handle);
74handle = IntPtr.Zero;
75}
76
77public bool AddProcess(Process process)
78{
79try { return AddProcess(process.Handle); }
80catch { }
81
82return false;
83}
84
85public bool AddProcess(IntPtr processHandle)
86{
87return AssignProcessToJobObject(handle, processHandle);
88}
89
90public bool AddProcess(int processId)
91{
92return AddProcess(Process.GetProcessById(processId).Handle);
93}
94}
95
96#region Helper classes
97
98[StructLayout(LayoutKind.Sequential)]
99struct IO_COUNTERS
100{
101public UInt64 ReadOperationCount;
102public UInt64 WriteOperationCount;
103public UInt64 OtherOperationCount;
104public UInt64 ReadTransferCount;
105public UInt64 WriteTransferCount;
106public UInt64 OtherTransferCount;
107}
108
109
110[StructLayout(LayoutKind.Sequential)]
111struct JOBOBJECT_BASIC_LIMIT_INFORMATION
112{
113public Int64 PerProcessUserTimeLimit;
114public Int64 PerJobUserTimeLimit;
115public UInt32 LimitFlags;
116public UIntPtr MinimumWorkingSetSize;
117public UIntPtr MaximumWorkingSetSize;
118public UInt32 ActiveProcessLimit;
119public UIntPtr Affinity;
120public UInt32 PriorityClass;
121public UInt32 SchedulingClass;
122}
123
124[StructLayout(LayoutKind.Sequential)]
125public struct SECURITY_ATTRIBUTES
126{
127public UInt32 nLength;
128public IntPtr lpSecurityDescriptor;
129public Int32 bInheritHandle;
130}
131
132[StructLayout(LayoutKind.Sequential)]
133struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
134{
135public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
136public IO_COUNTERS IoInfo;
137public UIntPtr ProcessMemoryLimit;
138public UIntPtr JobMemoryLimit;
139public UIntPtr PeakProcessMemoryUsed;
140public UIntPtr PeakJobMemoryUsed;
141}
142
143public enum JobObjectInfoType
144{
145AssociateCompletionPortInformation = 7,
146BasicLimitInformation = 2,
147BasicUIRestrictions = 4,
148EndOfJobTimeInformation = 6,
149ExtendedLimitInformation = 9,
150SecurityLimitInformation = 5,
151GroupInformation = 11
152}
153
154#endregion
155
156}