You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Job.cs 5.2 kB

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