コード例 #1
0
        public static void Main(String[] args)
        {
            uint          maxmem   = 0;
            List <String> procargs = null;
            bool          showhelp = false;
            int           pid      = 0;

            var p = new OptionSet()
            {
                { "m|maxmem=", "Max committed memory usage in bytes (accepted suffixes: K, M or G).",
                  v => {
                      if (v == null)
                      {
                          return;
                      }
                      if (v.EndsWith("K", StringComparison.OrdinalIgnoreCase))
                      {
                          maxmem = UInt32.Parse(v.Substring(0, v.Length - 1)) << 10;
                          return;
                      }
                      if (v.EndsWith("M", StringComparison.OrdinalIgnoreCase))
                      {
                          maxmem = UInt32.Parse(v.Substring(0, v.Length - 1)) << 20;
                          return;
                      }
                      if (v.EndsWith("G", StringComparison.OrdinalIgnoreCase))
                      {
                          maxmem = UInt32.Parse(v.Substring(0, v.Length - 1)) << 30;
                          return;
                      }
                      maxmem = UInt32.Parse(v);
                  } },
                { "p|pid=", "Attach to an already running process", (int v) => pid = v },
                { "h|help", "Show this message and exit", v => showhelp = v != null },
                { "?", "Show this message and exit", v => showhelp = v != null }
            };


            try {
                procargs = p.Parse(args);
            } catch (OptionException ex) {
                Console.Write("ERROR: invalid argument ");
                Console.WriteLine(ex.Message);
                Console.WriteLine();
                showhelp = true;
            } catch (FormatException) {
                Console.WriteLine("ERROR: invalid memory constraint");
                Console.WriteLine();
                showhelp = true;
            }

            if (!showhelp && (procargs.Count == 0 && pid == 0) || (pid > 0 && procargs.Count > 0))
            {
                Console.WriteLine("ERROR: please provide either process name to start or PID of the already running process");
                Console.WriteLine();
                showhelp = true;
            }

            if (showhelp)
            {
                ShowHelp(p);
                return;
            }

            IntPtr hJob, hIOCP, hProcess;

            hJob = hIOCP = hProcess = IntPtr.Zero;
            PROCESS_INFORMATION pi = new PROCESS_INFORMATION();
            Thread listener        = null;

            try {
                if (pid > 0)
                {
                    // open existing process
                    hProcess = CheckResult(ApiMethods.OpenProcess(ProcessAccessFlags.AllAccess, false, pid));
                }
                else
                {
                    // start suspended process
                    pi       = StartSuspendedProcess(procargs);
                    hProcess = pi.hProcess;
                }

                var securityAttributes = new SECURITY_ATTRIBUTES();
                securityAttributes.nLength = Marshal.SizeOf(securityAttributes);

                hJob = CheckResult(ApiMethods.CreateJobObject(ref securityAttributes, "procgov-" + Guid.NewGuid()));

                // create completion port
                hIOCP = CheckResult(ApiMethods.CreateIoCompletionPort(ApiMethods.INVALID_HANDLE_VALUE, IntPtr.Zero, IntPtr.Zero, 1));
                var assocInfo = new JOBOBJECT_ASSOCIATE_COMPLETION_PORT {
                    CompletionKey  = IntPtr.Zero,
                    CompletionPort = hIOCP
                };
                uint size = (uint)Marshal.SizeOf(assocInfo);
                CheckResult(ApiMethods.SetInformationJobObject(hJob, JOBOBJECTINFOCLASS.AssociateCompletionPortInformation,
                                                               ref assocInfo, size));

                // start listening thread
                listener = new Thread(CompletionPortListener);
                listener.Start(hIOCP);

                if (maxmem > 0.0f)
                {
                    // configure constraints
                    var limitInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION {
                        BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION {
                            LimitFlags = JobInformationLimitFlags.JOB_OBJECT_LIMIT_PROCESS_MEMORY
                                         | JobInformationLimitFlags.JOB_OBJECT_LIMIT_BREAKAWAY_OK
                                         | JobInformationLimitFlags.JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK
                        },
                        ProcessMemoryLimit = (UIntPtr)maxmem
                    };
                    size = (uint)Marshal.SizeOf(limitInfo);
                    CheckResult(ApiMethods.SetInformationJobObject(hJob, JOBOBJECTINFOCLASS.ExtendedLimitInformation,
                                                                   ref limitInfo, size));
                }

                // assign a process to a job to apply constraints
                CheckResult(ApiMethods.AssignProcessToJobObject(hJob, hProcess));

                // resume process main thread (if it was started by us)
                if (pid == 0)
                {
                    CheckResult(ApiMethods.ResumeThread(pi.hThread));
                    // and we can close the thread handle
                    CloseHandle(pi.hThread);
                }

                if (ApiMethods.WaitForSingleObject(hProcess, ApiMethods.INFINITE) == 0xFFFFFFFF)
                {
                    throw new Win32Exception();
                }
            } finally {
                CloseHandle(hIOCP);
                // wait for the listener thread to finish
                if (listener != null && listener.IsAlive)
                {
                    listener.Join();
                }

                CloseHandle(hProcess);
                CloseHandle(hJob);
            }
        }
コード例 #2
0
 internal static extern bool SetInformationJobObject(SafeJobObjectHandle hJob, JobObjectInformationClass JobObjectInfoClass, [In] ref JOBOBJECT_ASSOCIATE_COMPLETION_PORT lpJobObjectInfo, int cbJobObjectInfoLength);