Exemplo n.º 1
0
        public ProcessContainer(Process p, Job j)
        {
            _proc  = p;
            _job   = j;
            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()));
            }

            // Set the value to an unknown
            Result = InteractionResult.Unknown;
        }
Exemplo n.º 2
0
        public Job()
        {
            const uint JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000;

            const uint JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x800;

            _handle = CreateJobObject(IntPtr.Zero, null);

            var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
            {
                LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_BREAKAWAY_OK
            };

            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()));
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AttachedChildProcessJob"/> class.
        /// </summary>
        /// <param name="process">The process.</param>
        public AttachedChildProcessJob(Process process)
        {
            jobHandle = CreateJobObject(IntPtr.Zero, null);

            var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION
                {
                    LimitFlags = JOBOBJECTLIMIT.KillOnJobClose
                }
            };

            int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));

            var extendedInfoPtr = Marshal.AllocHGlobal(length);

            Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

            if (!SetInformationJobObject(jobHandle, JOBOBJECTINFOCLASS.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
            {
                return;
            }

            AssignProcessToJobObject(jobHandle, process.Handle);
        }
Exemplo n.º 4
0
        public ChildProcessManager(ulong memoryLimit)
        {
            _handle = new SafeJobHandle(CreateJobObject(IntPtr.Zero, null));

            var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
            {
                LimitFlags = 0x00000100
            };

            var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                BasicLimitInformation = info,
                ProcessMemoryLimit    = (UIntPtr)memoryLimit
            };

            var length          = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            var extendedInfoPtr = Marshal.AllocHGlobal(length);

            Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

            if (!SetInformationJobObject(_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr,
                                         (uint)length))
            {
                throw new InvalidOperationException($"Unable to set information.  Error: {Marshal.GetLastWin32Error()}");
            }
        }
Exemplo n.º 5
0
        private static SafeFileHandle CreateJobHandle()
        {
            var handle = NativeMethods.CreateJobObject(IntPtr.Zero, null);

            if (handle == null)
            {
                throw new LastWin32ErrorException("Error creating job handle");
            }

            var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();

            info.LimitFlags = 0x2000;

            var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();

            extendedInfo.BasicLimitInformation = info;

            int length          = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            var extendedInfoPtr = Marshal.AllocHGlobal(length);

            try {
                Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

                if (!NativeMethods.SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
                {
                    throw new LastWin32ErrorException("Unable to set job information");
                }

                return(handle);
            }
            finally {
                Marshal.FreeHGlobal(extendedInfoPtr);
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Constructor
        /// </summary>
        public ManagedProcessGroup()
        {
            if (SupportsJobObjects)
            {
                // Create the job object that the child process will be added to
                JobHandle = CreateJobObject(IntPtr.Zero, IntPtr.Zero);
                if (JobHandle == null)
                {
                    throw new Win32Exception();
                }

                // Configure the job object to terminate the processes added to it when the handle is closed
                JOBOBJECT_EXTENDED_LIMIT_INFORMATION LimitInformation = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
                LimitInformation.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_BREAKAWAY_OK;

                int    Length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
                IntPtr LimitInformationPtr = Marshal.AllocHGlobal(Length);
                Marshal.StructureToPtr(LimitInformation, LimitInformationPtr, false);

                if (SetInformationJobObject(JobHandle, JobObjectExtendedLimitInformation, LimitInformationPtr, Length) == 0)
                {
                    throw new Win32Exception();
                }
            }
        }
Exemplo n.º 7
0
        public Job()
        {
            handle = CreateJobObject(IntPtr.Zero, null);
            if (handle.IsInvalid)
            {
                throw new Win32Exception();
            }

            var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION
                {
                    LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
                }
            };

            int    cbJobObjectInfo = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            IntPtr lpJobObjectInfo = Marshal.AllocHGlobal(cbJobObjectInfo);

            try
            {
                Marshal.StructureToPtr(extendedInfo, lpJobObjectInfo, false);

                if (!SetInformationJobObject(handle,
                                             JobObjectInfoType.ExtendedLimitInformation,
                                             ref extendedInfo, cbJobObjectInfo))
                {
                    throw new Win32Exception();
                }
            }
            finally
            {
                Marshal.FreeHGlobal(lpJobObjectInfo);
            }
        }
Exemplo n.º 8
0
        public static IntPtr CreateKillOnCloseJob()
        {
            IntPtr job = CreateJobObject(IntPtr.Zero, null);

            if (job == IntPtr.Zero)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
            var info         = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
            int returnLength = 0;

            if (!QueryInformationJobObject(job, JOBOBJECTINFOCLASS.ExtendedLimitInformation, ref info, Marshal.SizeOf(info), ref returnLength))
            {
                var error = Marshal.GetLastWin32Error();
                CloseHandle(job);
                throw new Win32Exception(error);
            }
            info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_BREAKAWAY_OK;

            if (!SetInformationJobObject(job, JOBOBJECTINFOCLASS.ExtendedLimitInformation, ref info, (uint)Marshal.SizeOf(info)))
            {
                var error = Marshal.GetLastWin32Error();
                CloseHandle(job);
                throw new Win32Exception(error);
            }

            return(job);
        }
        public unsafe WindowsProcessKillJob()
        {
            jobHandle = Kernel32.CreateJobObject(IntPtr.Zero, IntPtr.Zero);
            if (jobHandle == IntPtr.Zero)
            {
                throw new Win32Exception();
            }
            try
            {
                var limitInformation = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
                {
                    BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION
                    {
                        LimitFlags = JOBOBJECT_BASIC_LIMIT_FLAGS.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
                    }
                };

                var cb = sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION);

                if (!Kernel32.SetInformationJobObject(jobHandle, JOBOBJECTINFOCLASS.JobObjectExtendedLimitInformation, ref limitInformation, (uint)cb))
                {
                    throw new Win32Exception();
                }
            }
            catch (Exception)
            {
                Kernel32.CloseHandle(jobHandle);
                throw;
            }
        }
Exemplo n.º 10
0
        public static IntPtr Create()
        {
            /*
             * Windows will automatically close any open job handles when our process terminates.
             * This can be verified by using SysInternals' readHandle utility. When the job handle
             * is closed, the child processes will be killed.
             *
             * This feature requires Windows 8 or later. To support Windows 7 requires
             * registry settings to be added if you are using Visual Studio plus an
             * app.manifest change.
             */
            if (!Environment.OSVersion.IsWindows8OrHigher())
            {
                return(IntPtr.Zero);
            }

            // The job name is optional (and can be null) but it helps with diagnostics.
            //  If it's not null, it has to be unique. Use SysInternals' Handle command-line
            //  utility: handle -a ChildProcessTracker
            string jobName   = "ChildProcessTracker" + Process.GetCurrentProcess().Id;
            IntPtr jobHandle = Win32.CreateJobObject(IntPtr.Zero, jobName);

            JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
            {
                LimitFlags = JobObjectLimitEnum.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
            };

            // This is the key flag. When our process is killed, Windows will automatically
            //  close the job handle, and when that happens, we want the child processes to
            //  be killed, too.
            JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION {
                BasicLimitInformation = info
            };

            int    length          = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);

            try
            {
                Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

                if (!Win32.SetInformationJobObject(jobHandle, JobObjectInfoTypeEnum.ExtendedLimitInformation,
                                                   extendedInfoPtr, (uint)length))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                Marshal.FreeHGlobal(extendedInfoPtr);
            }

            return(jobHandle);
        }
Exemplo n.º 11
0
        static void AttachChildProcessToThisProcess(Process proc)
        {
            //Attach 'proc' process to this process, so that it's closed along with this process

            try
            {
                if (ghJob == IntPtr.Zero)
                {
                    ghJob = CreateJobObject(IntPtr.Zero, "");                                   //It will be closed automatically when this process exits or is terminated

                    if (ghJob == IntPtr.Zero)
                    {
                        throw new Win32Exception();
                    }
                }

                JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
                info.LimitFlags = JOBOBJECTLIMIT.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

                JOBOBJECT_EXTENDED_LIMIT_INFORMATION exInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
                exInfo.BasicLimitInformation = info;

                int    nLength   = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
                IntPtr exInfoPtr = Marshal.AllocHGlobal(nLength);

                try
                {
                    Marshal.StructureToPtr(exInfo, exInfoPtr, false);

                    if (!SetInformationJobObject(ghJob, JobObjectInfoType.ExtendedLimitInformation, exInfoPtr, (uint)nLength))
                    {
                        throw new Win32Exception();
                    }

                    //And attach the process
                    if (!AssignProcessToJobObject(ghJob, proc.Handle))
                    {
                        throw new Win32Exception();
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(exInfoPtr);
                }
            }
            catch (Exception ex)
            {
                //Error
                gEventLog.logMessage(EventLogMsgType.ELM_TYP_Error, "Failed to assign miner job: " + ex.ToString());
                OutputConsoleError("ERROR: Failed to assign miner job: " + ex.ToString());
            }
        }
Exemplo n.º 12
0
        /// <summary>
        /// Sets limits.
        /// </summary>
        /// <param name="activeProcessLimit">The number of processes that can be added to the job object.</param>
        /// <param name="jobMemoryLimitInBytes">The total amount of memory that can be consumed by all processes in the job object.</param>
        /// <param name="limitFlags">The limits that are in effect.</param>
        /// <param name="processMemoryLimitInBytes">The maximum number of bytes a process can consume.</param>
        public void SetLimits(
            uint? activeProcessLimit = null,
            ulong? jobMemoryLimitInBytes = null,
            JOB_OBJECT_LIMIT_FLAGS limitFlags = JOB_OBJECT_LIMIT_FLAGS.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,
            ulong? processMemoryLimitInBytes = null)
        {
            this.tracer.Trace(nameof(JobObject), "Setting limits");

            var extendedLimitInformation = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                BasicLimitInformation =
                {
                    LimitFlags = limitFlags,
                },
            };

            if (activeProcessLimit.HasValue)
            {
                extendedLimitInformation.BasicLimitInformation.ActiveProcessLimit = activeProcessLimit.GetValueOrDefault();
                extendedLimitInformation.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_FLAGS.JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
            }

            if (jobMemoryLimitInBytes.HasValue)
            {
                extendedLimitInformation.JobMemoryLimit = new UIntPtr(jobMemoryLimitInBytes.GetValueOrDefault());
                extendedLimitInformation.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_FLAGS.JOB_OBJECT_LIMIT_JOB_MEMORY;
            }

            if (processMemoryLimitInBytes.HasValue)
            {
                extendedLimitInformation.ProcessMemoryLimit = new UIntPtr(processMemoryLimitInBytes.GetValueOrDefault());
                extendedLimitInformation.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_FLAGS.JOB_OBJECT_LIMIT_PROCESS_MEMORY;
            }

            // Apply the limits to the job object.
            using (var nativeExtendedLimitInformation = new SafeHGlobalBuffer(Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION))))
            {
                Marshal.StructureToPtr(extendedLimitInformation, nativeExtendedLimitInformation.DangerousGetHandle(), fDeleteOld: false);

                if (!Methods.SetInformationJobObject(
                        this.handle,
                        JOB_OBJECT_INFO_CLASS.JobObjectExtendedLimitInformation,
                        nativeExtendedLimitInformation.DangerousGetHandle(),
                        nativeExtendedLimitInformation.Size))
                {
                    throw
                        new SandboxException(
                            "Unable to set job object limit information",
                            new Win32Exception());
                }
            }
        }
Exemplo n.º 13
0
        static ChildProcessTracker()
        {
            // This feature requires Windows 8 or later. To support Windows 7 requires
            //  registry settings to be added if you are using Visual Studio plus an
            //  app.manifest change.
            //  https://stackoverflow.com/a/4232259/386091
            //  https://stackoverflow.com/a/9507862/386091
            if (Environment.OSVersion.Version < new Version(6, 2))
            {
                return;
            }

            // The job name is optional (and can be null) but it helps with diagnostics.
            //  If it's not null, it has to be unique. Use SysInternals' Handle command-line
            //  utility: handle -a ChildProcessTracker
            string jobName = "ChildProcessTracker" + Process.GetCurrentProcess().Id;

            s_jobHandle = CreateJobObject(IntPtr.Zero, jobName);

            var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
            {
                // This is the key flag. When our process is killed, Windows will automatically
                //  close the job handle, and when that happens, we want the child processes to
                //  be killed, too.
                LimitFlags = JOBOBJECTLIMIT.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
            };

            var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                BasicLimitInformation = info
            };

            int    length          = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);

            try
            {
                Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

                if (!SetInformationJobObject(s_jobHandle, JobObjectInfoType.ExtendedLimitInformation,
                                             extendedInfoPtr, (uint)length))
                {
                    throw new Win32Exception();
                }
            }
            finally
            {
                Marshal.FreeHGlobal(extendedInfoPtr);
            }
        }
Exemplo n.º 14
0
        static ProcessHelper()
        {
            job = CreateJobObject(IntPtr.Zero, null);

            JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
            info.LimitFlags = 0x2000;

            JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
            extendedInfo.BasicLimitInformation = info;

            int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
            Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

            SetInformationJobObject(job, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length);
        }
Exemplo n.º 15
0
    /// <summary>
    /// Initializes a new instance of the <see cref="ProcessJobTracker"/> class.
    /// </summary>
    public ProcessJobTracker()
    {
        if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            return;
        }

        // The job name is optional (and can be null) but it helps with diagnostics.
        //  If it's not null, it has to be unique. Use SysInternals' Handle command-line
        //  utility: handle -a ChildProcessTracker
        string jobName = nameof(ProcessJobTracker) + Process.GetCurrentProcess().Id;

        this.jobHandle = CreateJobObject(IntPtr.Zero, jobName);

        var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
        {
            BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION
            {
                LimitFlags = JOB_OBJECT_LIMIT_FLAGS.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,
            },
        };

        // This code can be a lot simpler if we use pointers, but since this class is so generally interesting
        // and may be copied and pasted to other projects that prefer to avoid unsafe code, we use Marshal and IntPtr's instead.
        int    length        = Marshal.SizeOf(extendedInfo);
        IntPtr pExtendedInfo = Marshal.AllocHGlobal(length);

        try
        {
            Marshal.StructureToPtr(extendedInfo, pExtendedInfo, fDeleteOld: false);
            try
            {
                if (!SetInformationJobObject(this.jobHandle, JOBOBJECTINFOCLASS.JobObjectExtendedLimitInformation, pExtendedInfo, (uint)length))
                {
                    throw new Win32Exception();
                }
            }
            finally
            {
                Marshal.DestroyStructure <JOBOBJECT_EXTENDED_LIMIT_INFORMATION>(pExtendedInfo);
            }
        }
        finally
        {
            Marshal.FreeHGlobal(pExtendedInfo);
        }
    }
        public static void Start(Process process = null)
        {
            // this is here to make it so if the player crashes
            // the process it started is killed along with it
            if (!Started)
            {
                if (jobHandle == IntPtr.Zero)
                {
                    jobHandle = CreateJobObject(IntPtr.Zero, null);

                    if (jobHandle == IntPtr.Zero)
                    {
                        throw new JobObjectException("Could not create the Job Object.");
                    }
                }

                JOBOBJECT_BASIC_LIMIT_INFORMATION jobobjectBasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION {
                    LimitFlags = JOB_OBJECT_LIMIT.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
                };

                JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobobjectExtendedLimitInformation = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION {
                    BasicLimitInformation = jobobjectBasicLimitInformation
                };

                int    jobobjectExtendedLimitInformationSize    = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
                IntPtr jobobjectExtendedLimitInformationPointer = Marshal.AllocHGlobal(jobobjectExtendedLimitInformationSize);

                Marshal.StructureToPtr(jobobjectExtendedLimitInformation, jobobjectExtendedLimitInformationPointer, false);

                bool result = SetInformationJobObject(jobHandle, JOBOBJECTINFOCLASS.JobObjectExtendedLimitInformation, jobobjectExtendedLimitInformationPointer, (uint)jobobjectExtendedLimitInformationSize);

                Marshal.FreeHGlobal(jobobjectExtendedLimitInformationPointer);

                if (process == null)
                {
                    process = Process.GetCurrentProcess();
                }

                if (!result || !AssignProcessToJobObject(jobHandle, process.Handle))
                {
                    throw new JobObjectException("Could not set the Job Object Information or assign the Process to the Job Object.");
                }

                Started = true;
            }
        }
Exemplo n.º 17
0
        public void Init()
        {
            try
            {
                if (!m_IsInit)
                {
                    m_JobHandle = CreateJobObject(IntPtr.Zero, null);

                    if (m_JobHandle == IntPtr.Zero)
                    {
                        throw new Exception("Failed to create job handle");
                    }

                    var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION()
                    {
                        BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION()
                        {
                            LimitFlags = 0x2000
                        }
                    };

                    var length          = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
                    var extendedInfoPtr = Marshal.AllocHGlobal(length);

                    Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

                    if (!SetInformationJobObject(m_JobHandle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
                    {
                        throw new Exception(string.Format("Unable to set information.  Error: {0}", Marshal.GetLastWin32Error()));
                    }

                    m_Logger.Log($"Job initiated: {m_JobHandle}", LoggerMessageSeverity_e.Debug);
                    m_IsInit = true;
                }
                else
                {
                    throw new Exception("Job is already initialized");
                }
            }
            catch (Exception ex)
            {
                m_Logger.Log(ex);
                throw;
            }
        }
Exemplo n.º 18
0
    public Job()
    {
        m_handle = CreateJobObject(null, null);
        JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();

        info.LimitFlags = 0x2000;
        JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();

        extendedInfo.BasicLimitInformation = info;
        int    length          = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
        IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);

        Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
        if (!SetInformationJobObject(m_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
        {
            throw new Exception(string.Format("Unable to set information.  Error: {0}", Marshal.GetLastWin32Error()));
        }
    }
Exemplo n.º 19
0
        public static JobObject CreateAsKillOnJobClose()
        {
            var job = new JobObject();

            var jobInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION()
            {
                BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION()
                {
                    LimitFlags = JobObjectLimit.KillOnJobClose
                },
            };
            var size = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));

            if (!Native.SetInformationJobObject(job.SafeHandle, JobObjectInfoClass.ExtendedLimitInformation, ref jobInfo, size))
            {
                throw new Win32Exception();
            }

            return(job);
        }
Exemplo n.º 20
0
        public Job()
        {
            jobObjecthandler = CreateJobObject(IntPtr.Zero, "mongod");

            var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION {
                    LimitFlags = 0x2000
                }
            };

            int extendedInfoObjLength = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            var extendedInfoPtr       = Marshal.AllocHGlobal(extendedInfoObjLength);

            Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

            if (!SetInformationJobObject(jobObjecthandler, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)extendedInfoObjLength))
            {
                throw new InvalidOperationException($"Unable to set information.  win32 error: {Marshal.GetLastWin32Error()}");
            }
        }
Exemplo n.º 21
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AttachedChildProcessJob"/> class.
        /// </summary>
        /// <param name="process">The process.</param>
        public AttachedChildProcessJob(Process process)
        {
            jobHandle = CreateJobObject(IntPtr.Zero, null);

            var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION
                {
                    LimitFlags = JOBOBJECTLIMIT.KillOnJobClose
                }
            };

            int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            
            var extendedInfoPtr = Marshal.AllocHGlobal(length);
            Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

            if (!SetInformationJobObject(jobHandle, JOBOBJECTINFOCLASS.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
                return;

            AssignProcessToJobObject(jobHandle, process.Handle);
        }
Exemplo n.º 22
0
    private static IntPtr IntiailizeProcessTracker()
    {
        // Requires Win8 or later
        if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || Environment.OSVersion.Version < new Version(6, 2))
        {
            return(IntPtr.Zero);
        }

        // Job name is optional but helps with diagnostics.  Job name must be unique if non-null.
        var jobHandle = CreateJobObject(IntPtr.Zero, name: $"ProcessTracker{Environment.ProcessId}");

        var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
        {
            BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION
            {
                LimitFlags = JOBOBJECTLIMIT.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
            }
        };

        var length          = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
        var extendedInfoPtr = Marshal.AllocHGlobal(length);

        try
        {
            Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

            if (!SetInformationJobObject(jobHandle, JobObjectInfoType.ExtendedLimitInformation,
                                         extendedInfoPtr, (uint)length))
            {
                throw new Win32Exception();
            }
        }
        finally
        {
            Marshal.FreeHGlobal(extendedInfoPtr);
        }

        return(jobHandle);
    }
Exemplo n.º 23
0
        private static void SetProcessGroupLimits(IntPtr hGroupObject, uint limitFlags)
        {
            IntPtr hLimitInfo = IntPtr.Zero;

            JOBOBJECT_EXTENDED_LIMIT_INFORMATION limitInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();

            try
            {
                //HACK: For some reason, the SetInformationJobObject API returns a failure if you use BASIC_LIMIT structure
                //instead of the EXTENDED limit structure, even if we only care about the BASIC one.

                int returnLength  = 0;
                int limitInfoSize = Marshal.SizeOf(limitInfo);
                hLimitInfo = Marshal.AllocHGlobal(limitInfoSize);

                //Retrieve the current limit info
                if (!QueryInformationJobObject(hGroupObject, JOBOBJECTINFOCLASS.JobObjectExtendedLimitInformation, hLimitInfo, limitInfoSize, ref returnLength))
                {
                    throw new Win32Exception();
                }

                //Marshall the data between managed and unmanaged memory
                Marshal.PtrToStructure(hLimitInfo, limitInfo);
                limitInfo.BasicLimitInformation.LimitFlags |= limitFlags;
                Marshal.StructureToPtr(limitInfo, hLimitInfo, false);

                if (!SetInformationJobObject(hGroupObject, JOBOBJECTINFOCLASS.JobObjectExtendedLimitInformation, hLimitInfo, limitInfoSize))
                {
                    throw new Win32Exception();
                }
            }
            finally
            {
                if (hLimitInfo != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(hLimitInfo);
                }
            }
        }
Exemplo n.º 24
0
        /// <summary>
        /// Creates a new <see cref="ChildProcessManager"/>.
        /// </summary>
        public ChildProcessManager()
        {
            if (Common.IsPosixEnvironment)
            {
                // On non-Windows operating systems we just track associated processes
                m_childProcesses = new List <WeakReference <Process> >();
            }
            else
            {
                // Let safe handle manage terminations on Windows
                GC.SuppressFinalize(this);

                // On Windows we add child processes to a job object such that when the job
                // is terminated, so are the child processes. Since safe handle ensures proper
                // closing of job handle, child processes will be terminated even if parent
                // process is abnormally terminated
                m_jobHandle = new SafeJobHandle(CreateJobObject(IntPtr.Zero, null));

                JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
                {
                    LimitFlags = 0x2000
                };

                JOBOBJECT_EXTENDED_LIMIT_INFORMATION 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(m_jobHandle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
                {
                    throw new InvalidOperationException($"Unable to set information for ChildProcessManager job. Error: {Marshal.GetLastWin32Error()}");
                }
            }
        }
 public WindowsProcessKillJob(ILog log)
 {
     this.log  = log.ForContext <WindowsProcessKillJob>();
     jobHandle = Kernel32.CreateJobObject(IntPtr.Zero, IntPtr.Zero);
     if (jobHandle == IntPtr.Zero)
     {
         throw new Win32Exception(Marshal.GetLastWin32Error());
     }
     try
     {
         var limitInformation = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
         {
             BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION
             {
                 LimitFlags = JOBOBJECT_BASIC_LIMIT_FLAGS.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
             }
         };
         var cb = Marshal.SizeOf((object)limitInformation);
         jobObjectInfoPtr = Marshal.AllocHGlobal(cb);
         try
         {
             Marshal.StructureToPtr((object)limitInformation, jobObjectInfoPtr, false);
             if (!Kernel32.SetInformationJobObject(jobHandle, JOBOBJECTINFOCLASS.JobObjectExtendedLimitInformation, jobObjectInfoPtr, (uint)cb))
             {
                 throw new Win32Exception(Marshal.GetLastWin32Error());
             }
         }
         catch (Exception)
         {
             Marshal.FreeHGlobal(jobObjectInfoPtr);
             throw;
         }
     }
     catch (Exception)
     {
         Kernel32.CloseHandle(jobHandle);
         throw;
     }
 }
Exemplo n.º 26
0
        public JobObject()
        {
            handle = NativeMethods.CreateJobObject(IntPtr.Zero, null);

            var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
            {
                LimitFlags = KillOnJobClose
            };

            var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                BasicLimitInformation = info
            };

            var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            var extendedInfoPtr = Marshal.AllocHGlobal(length);
            Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

            if (!NativeMethods.SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
            {
                throw new Exception(string.Format("Unable to set information.  Error: {0}", Marshal.GetLastWin32Error()));
            }
        }
Exemplo n.º 27
0
        public ProcessJobTracker()
        {
            string jobName = nameof(ProcessJobTracker) + Process.GetCurrentProcess().Id;

            _jobHandle = Kernel32Wrapper.CreateJobObject(IntPtr.Zero, jobName);

            var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                BasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION
                {
                    LimitFlags = JOBOBJECTLIMIT.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,
                },
            };

            int    length        = Marshal.SizeOf(extendedInfo);
            IntPtr pExtendedInfo = Marshal.AllocHGlobal(length);

            try
            {
                Marshal.StructureToPtr(extendedInfo, pExtendedInfo, false);
                try
                {
                    if (!Kernel32Wrapper.SetInformationJobObject(_jobHandle, JobObjectInfoType.ExtendedLimitInformation, pExtendedInfo, (uint)length))
                    {
                        throw new Win32Exception();
                    }
                }
                finally
                {
                    Marshal.DestroyStructure <JOBOBJECT_EXTENDED_LIMIT_INFORMATION>(pExtendedInfo);
                }
            }
            finally
            {
                Marshal.FreeHGlobal(pExtendedInfo);
            }
        }
Exemplo n.º 28
0
        public Job()
        {
            handle = CreateJobObject(IntPtr.Zero, null);
            var extendedInfoPtr = IntPtr.Zero;
            var info            = new JOBOBJECT_BASIC_LIMIT_INFORMATION
            {
                LimitFlags = 0x2000
            };

            var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                BasicLimitInformation = info
            };

            try
            {
                int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
                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()));
                }
            }
            finally
            {
                if (extendedInfoPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(extendedInfoPtr);
                    extendedInfoPtr = IntPtr.Zero;
                }
            }
        }
Exemplo n.º 29
0
        public JobObject()
        {
            handle = NativeMethods.CreateJobObject(IntPtr.Zero, null);

            var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
            {
                LimitFlags = KillOnJobClose
            };

            var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                BasicLimitInformation = info
            };

            var length          = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            var extendedInfoPtr = Marshal.AllocHGlobal(length);

            Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

            if (!NativeMethods.SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
            {
                throw new Exception(string.Format("Unable to set information.  Error: {0}", Marshal.GetLastWin32Error()));
            }
        }
Exemplo n.º 30
0
        public ChildProcessManager()
        {
            _handle = new SafeJobHandle(CreateJobObject(IntPtr.Zero, null));

            var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
            {
                LimitFlags = 0x2000
            };

            var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                BasicLimitInformation = info
            };

            var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            var extendedInfoPtr = Marshal.AllocHGlobal(length);
            Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

            if (!SetInformationJobObject(_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr,
                    (uint)length))
            {
                throw new InvalidOperationException($"Unable to set information.  Error: {Marshal.GetLastWin32Error()}");
            }
        }
Exemplo n.º 31
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);
            }
        }
Exemplo n.º 32
0
        /// <summary>
        /// Spawns a new managed process.
        /// </summary>
        /// <param name="FileName">Path to the executable to be run</param>
        /// <param name="CommandLine">Command line arguments for the process</param>
        /// <param name="WorkingDirectory">Working directory for the new process. May be null to use the current working directory.</param>
        /// <param name="Environment">Environment variables for the new process. May be null, in which case the current process' environment is inherited</param>
        /// <param name="Input">Text to be passed via stdin to the new process. May be null.</param>
        public ManagedProcess(string FileName, string CommandLine, string WorkingDirectory, IReadOnlyDictionary <string, string> Environment, string Input, ManagedProcessPriority Priority, ulong MemoryLimit)
        {
            // Create the job object that the child process will be added to
            JobHandle = CreateJobObject(IntPtr.Zero, IntPtr.Zero);
            if (JobHandle == null)
            {
                throw new Win32Exception();
            }

            // Configure the job object to terminate the processes added to it when the handle is closed
            JOBOBJECT_EXTENDED_LIMIT_INFORMATION LimitInformation = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();

            LimitInformation.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_PROCESS_MEMORY;
            LimitInformation.ProcessMemoryLimit = new UIntPtr(MemoryLimit);

            int    Length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            IntPtr LimitInformationPtr = Marshal.AllocHGlobal(Length);

            Marshal.StructureToPtr(LimitInformation, LimitInformationPtr, false);

            if (SetInformationJobObject(JobHandle, JobObjectExtendedLimitInformation, LimitInformationPtr, Length) == 0)
            {
                throw new Win32Exception();
            }

            // Create the child process
            IntPtr         EnvironmentBlock = IntPtr.Zero;
            SafeFileHandle StdInRead        = null;
            SafeFileHandle StdOutWrite      = null;
            SafeWaitHandle StdErrWrite      = null;

            try
            {
                // Create stdin and stdout pipes for the child process. We'll close the handles for the child process' ends after it's been created.
                SECURITY_ATTRIBUTES SecurityAttributes = new SECURITY_ATTRIBUTES();
                SecurityAttributes.bInheritHandle = 1;

                if (CreatePipe(out StdInRead, out StdInWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdInWrite, HANDLE_FLAG_INHERIT, 0) == 0)
                {
                    throw new Win32Exception();
                }
                if (CreatePipe(out StdOutRead, out StdOutWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdOutRead, HANDLE_FLAG_INHERIT, 0) == 0)
                {
                    throw new Win32Exception();
                }
                if (DuplicateHandle(GetCurrentProcess(), StdOutWrite, GetCurrentProcess(), out StdErrWrite, DUPLICATE_SAME_ACCESS, true, 0) == 0)
                {
                    throw new Win32Exception();
                }

                // Create the environment block for the child process, if necessary.
                if (Environment != null)
                {
                    // The native format for the environment block is a sequence of null terminated strings with a final null terminator.
                    List <byte> EnvironmentBytes = new List <byte>();
                    foreach (KeyValuePair <string, string> Pair in Environment)
                    {
                        EnvironmentBytes.AddRange(Encoding.UTF8.GetBytes(Pair.Key));
                        EnvironmentBytes.Add((byte)'=');
                        EnvironmentBytes.AddRange(Encoding.UTF8.GetBytes(Pair.Value));
                        EnvironmentBytes.Add((byte)0);
                    }
                    EnvironmentBytes.Add((byte)0);

                    // Allocate an unmanaged block of memory to store it.
                    EnvironmentBlock = Marshal.AllocHGlobal(EnvironmentBytes.Count);
                    Marshal.Copy(EnvironmentBytes.ToArray(), 0, EnvironmentBlock, EnvironmentBytes.Count);
                }

                // Set the startup parameters for the new process
                STARTUPINFO StartupInfo = new STARTUPINFO();
                StartupInfo.cb         = Marshal.SizeOf(StartupInfo);
                StartupInfo.hStdInput  = StdInRead;
                StartupInfo.hStdOutput = StdOutWrite;
                StartupInfo.hStdError  = StdErrWrite;
                StartupInfo.dwFlags    = STARTF_USESTDHANDLES;

                PROCESS_INFORMATION ProcessInfo = new PROCESS_INFORMATION();
                try
                {
                    // Get the flags to create the new process
                    ProcessCreationFlags Flags = ProcessCreationFlags.CREATE_NO_WINDOW | ProcessCreationFlags.CREATE_SUSPENDED | ProcessCreationFlags.CREATE_BREAKAWAY_FROM_JOB;
                    switch (Priority)
                    {
                    case ManagedProcessPriority.BelowNormal:
                        Flags |= ProcessCreationFlags.BELOW_NORMAL_PRIORITY_CLASS;
                        break;

                    case ManagedProcessPriority.Normal:
                        Flags |= ProcessCreationFlags.NORMAL_PRIORITY_CLASS;
                        break;

                    case ManagedProcessPriority.AboveNormal:
                        Flags |= ProcessCreationFlags.ABOVE_NORMAL_PRIORITY_CLASS;
                        break;
                    }

                    // Create the new process as suspended, so we can modify it before it starts executing (and potentially preempting us)
                    if (CreateProcess(null, new StringBuilder("\"" + FileName + "\" " + CommandLine), IntPtr.Zero, IntPtr.Zero, true, Flags, EnvironmentBlock, WorkingDirectory, StartupInfo, ProcessInfo) == 0)
                    {
                        throw new Win32Exception();
                    }

                    // Add it to our job object
                    if (AssignProcessToJobObject(JobHandle, ProcessInfo.hProcess) == 0)
                    {
                        throw new Win32Exception();
                    }

                    // Allow the thread to start running
                    if (ResumeThread(ProcessInfo.hThread) == -1)
                    {
                        throw new Win32Exception();
                    }

                    // If we have any input text, write it to stdin now
                    using (StreamWriter StdInWriter = new StreamWriter(new FileStream(StdInWrite, FileAccess.Write, 4096, false), Console.InputEncoding, 4096))
                    {
                        if (!String.IsNullOrEmpty(Input))
                        {
                            StdInWriter.WriteLine(Input);
                            StdInWriter.Flush();
                        }
                    }

                    // Create the stream objects for reading the process output
                    InnerStream = new FileStream(StdOutRead, FileAccess.Read, 4096, false);
                    ReadStream  = new StreamReader(InnerStream, Console.OutputEncoding);

                    // Wrap the process handle in a SafeFileHandle
                    ProcessHandle = new SafeFileHandle(ProcessInfo.hProcess, true);
                }
                finally
                {
                    if (ProcessInfo.hProcess != IntPtr.Zero && ProcessHandle == null)
                    {
                        CloseHandle(ProcessInfo.hProcess);
                    }
                    if (ProcessInfo.hThread != IntPtr.Zero)
                    {
                        CloseHandle(ProcessInfo.hThread);
                    }
                }
            }
            finally
            {
                if (EnvironmentBlock != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(EnvironmentBlock);
                    EnvironmentBlock = IntPtr.Zero;
                }
                if (StdInRead != null)
                {
                    StdInRead.Dispose();
                    StdInRead = null;
                }
                if (StdOutWrite != null)
                {
                    StdOutWrite.Dispose();
                    StdOutWrite = null;
                }
                if (StdErrWrite != null)
                {
                    StdErrWrite.Dispose();
                    StdErrWrite = null;
                }
            }
        }
 public static extern bool SetInformationJobObject(SafeJobHandle hJob, JobObjectInfoType infoType,
                                                   ref JOBOBJECT_EXTENDED_LIMIT_INFORMATION lpJobObjectInfo, int cbJobObjectInfoLength);
Exemplo n.º 34
0
		public ChildProcess(string FileName, string CommandLine, string Input)
		{
			JobHandle = CreateJobObject(IntPtr.Zero, IntPtr.Zero);
			if(JobHandle == null)
			{
				throw new Win32Exception();
			}

			JOBOBJECT_EXTENDED_LIMIT_INFORMATION LimitInformation = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
			LimitInformation.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

			int Length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
			IntPtr LimitInformationPtr = Marshal.AllocHGlobal(Length);
			Marshal.StructureToPtr(LimitInformation, LimitInformationPtr, false);

			if(SetInformationJobObject(JobHandle, JobObjectExtendedLimitInformation, LimitInformationPtr, Length) == 0)
			{
				throw new Win32Exception();
			}

			SafeFileHandle StdInRead = null;
			SafeFileHandle StdOutWrite = null;
			SafeWaitHandle StdErrWrite = null;
			try
			{
				SECURITY_ATTRIBUTES SecurityAttributes = new SECURITY_ATTRIBUTES();
				SecurityAttributes.bInheritHandle = 1;

				if(CreatePipe(out StdInRead, out StdInWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdInWrite, HANDLE_FLAG_INHERIT, 0) == 0)
				{
					throw new Win32Exception();
				}
				if(CreatePipe(out StdOutRead, out StdOutWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdOutRead, HANDLE_FLAG_INHERIT, 0) == 0)
				{
					throw new Win32Exception();
				}
				if(DuplicateHandle(GetCurrentProcess(), StdOutWrite, GetCurrentProcess(), out StdErrWrite, DUPLICATE_SAME_ACCESS, true, 0) == 0)
				{
					throw new Win32Exception();
				}

				STARTUPINFO StartupInfo = new STARTUPINFO();
                StartupInfo.cb = Marshal.SizeOf(StartupInfo);
				StartupInfo.hStdInput = StdInRead;
				StartupInfo.hStdOutput = StdOutWrite;
				StartupInfo.hStdError = StdErrWrite;
				StartupInfo.dwFlags = STARTF_USESTDHANDLES;

				PROCESS_INFORMATION ProcessInfo = new PROCESS_INFORMATION();
				try
				{
					if(CreateProcess(null, new StringBuilder("\"" + FileName + "\" " + CommandLine), IntPtr.Zero, IntPtr.Zero, true, CREATE_NO_WINDOW | CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB, new IntPtr(0), null, StartupInfo, ProcessInfo) == 0)
					{
						throw new Win32Exception();
					}
					if(AssignProcessToJobObject(JobHandle, ProcessInfo.hProcess) == 0)
					{
						throw new Win32Exception();
					}
					if(ResumeThread(ProcessInfo.hThread) == -1)
					{
						throw new Win32Exception();
					}

					using(StreamWriter StdInWriter = new StreamWriter(new FileStream(StdInWrite, FileAccess.Write, 4096, false), Console.InputEncoding, 4096))
					{
						if(!String.IsNullOrEmpty(Input))
						{
							StdInWriter.WriteLine(Input);
							StdInWriter.Flush();
						}
					}

					InnerStream = new FileStream(StdOutRead, FileAccess.Read, 4096, false);
					ReadStream = new StreamReader(InnerStream, Console.OutputEncoding);
					ProcessHandle = new SafeFileHandle(ProcessInfo.hProcess, true);
				}
				finally
				{
					if(ProcessInfo.hProcess != null && ProcessHandle == null)
					{
						CloseHandle(ProcessInfo.hProcess);
					}
					if(ProcessInfo.hThread != null)
					{
						CloseHandle(ProcessInfo.hThread);
					}
				}
			}
			finally
			{
				if(StdInRead != null)
				{
					StdInRead.Dispose();
					StdInRead = null;
				}
				if(StdOutWrite != null)
				{
					StdOutWrite.Dispose();
					StdOutWrite = null;
				}
				if(StdErrWrite != null)
				{
					StdErrWrite.Dispose();
					StdErrWrite = null;
				}
			}
		}
Exemplo n.º 35
0
        public ChildProcess(string FileName, string CommandLine, string Input)
        {
            JobHandle = CreateJobObject(IntPtr.Zero, IntPtr.Zero);
            if (JobHandle == null)
            {
                throw new Win32Exception();
            }

            JOBOBJECT_EXTENDED_LIMIT_INFORMATION LimitInformation = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();

            LimitInformation.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

            int    Length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            IntPtr LimitInformationPtr = Marshal.AllocHGlobal(Length);

            Marshal.StructureToPtr(LimitInformation, LimitInformationPtr, false);

            if (SetInformationJobObject(JobHandle, JobObjectExtendedLimitInformation, LimitInformationPtr, Length) == 0)
            {
                throw new Win32Exception();
            }

            SafeFileHandle StdInRead   = null;
            SafeFileHandle StdOutWrite = null;
            SafeWaitHandle StdErrWrite = null;

            try
            {
                SECURITY_ATTRIBUTES SecurityAttributes = new SECURITY_ATTRIBUTES();
                SecurityAttributes.bInheritHandle = 1;

                if (CreatePipe(out StdInRead, out StdInWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdInWrite, HANDLE_FLAG_INHERIT, 0) == 0)
                {
                    throw new Win32Exception();
                }
                if (CreatePipe(out StdOutRead, out StdOutWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdOutRead, HANDLE_FLAG_INHERIT, 0) == 0)
                {
                    throw new Win32Exception();
                }
                if (DuplicateHandle(GetCurrentProcess(), StdOutWrite, GetCurrentProcess(), out StdErrWrite, DUPLICATE_SAME_ACCESS, true, 0) == 0)
                {
                    throw new Win32Exception();
                }

                STARTUPINFO StartupInfo = new STARTUPINFO();
                StartupInfo.cb         = Marshal.SizeOf(StartupInfo);
                StartupInfo.hStdInput  = StdInRead;
                StartupInfo.hStdOutput = StdOutWrite;
                StartupInfo.hStdError  = StdErrWrite;
                StartupInfo.dwFlags    = STARTF_USESTDHANDLES;

                PROCESS_INFORMATION ProcessInfo = new PROCESS_INFORMATION();
                try
                {
                    if (CreateProcess(null, new StringBuilder("\"" + FileName + "\" " + CommandLine), IntPtr.Zero, IntPtr.Zero, true, CREATE_NO_WINDOW | CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB, new IntPtr(0), null, StartupInfo, ProcessInfo) == 0)
                    {
                        throw new Win32Exception();
                    }
                    if (AssignProcessToJobObject(JobHandle, ProcessInfo.hProcess) == 0)
                    {
                        throw new Win32Exception();
                    }
                    if (ResumeThread(ProcessInfo.hThread) == -1)
                    {
                        throw new Win32Exception();
                    }

                    using (StreamWriter StdInWriter = new StreamWriter(new FileStream(StdInWrite, FileAccess.Write, 4096, false), Console.InputEncoding, 4096))
                    {
                        if (!String.IsNullOrEmpty(Input))
                        {
                            StdInWriter.WriteLine(Input);
                            StdInWriter.Flush();
                        }
                    }

                    InnerStream   = new FileStream(StdOutRead, FileAccess.Read, 4096, false);
                    ReadStream    = new StreamReader(InnerStream, Console.OutputEncoding);
                    ProcessHandle = new SafeFileHandle(ProcessInfo.hProcess, true);
                }
                finally
                {
                    if (ProcessInfo.hProcess != null && ProcessHandle == null)
                    {
                        CloseHandle(ProcessInfo.hProcess);
                    }
                    if (ProcessInfo.hThread != null)
                    {
                        CloseHandle(ProcessInfo.hThread);
                    }
                }
            }
            finally
            {
                if (StdInRead != null)
                {
                    StdInRead.Dispose();
                    StdInRead = null;
                }
                if (StdOutWrite != null)
                {
                    StdOutWrite.Dispose();
                    StdOutWrite = null;
                }
                if (StdErrWrite != null)
                {
                    StdErrWrite.Dispose();
                    StdErrWrite = null;
                }
            }
        }
Exemplo n.º 36
0
 public static extern bool SetInformationJobObject(IntPtr hJob, int infoType
     , ref JOBOBJECT_EXTENDED_LIMIT_INFORMATION lpJobObjectInfo, int cbJobObjectInfoLength);
Exemplo n.º 37
0
		/// <summary>
		/// Spawns a new managed process.
		/// </summary>
		/// <param name="FileName">Path to the executable to be run</param>
		/// <param name="CommandLine">Command line arguments for the process</param>
		/// <param name="WorkingDirectory">Working directory for the new process. May be null to use the current working directory.</param>
		/// <param name="Environment">Environment variables for the new process. May be null, in which case the current process' environment is inherited</param>
		/// <param name="Input">Text to be passed via stdin to the new process. May be null.</param>
		public ManagedProcess(string FileName, string CommandLine, string WorkingDirectory, IReadOnlyDictionary<string, string> Environment, string Input, ManagedProcessPriority Priority)
		{
			// Create the job object that the child process will be added to
			JobHandle = CreateJobObject(IntPtr.Zero, IntPtr.Zero);
			if(JobHandle == null)
			{
				throw new Win32Exception();
			}

			// Configure the job object to terminate the processes added to it when the handle is closed
			JOBOBJECT_EXTENDED_LIMIT_INFORMATION LimitInformation = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
			LimitInformation.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

			int Length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
			IntPtr LimitInformationPtr = Marshal.AllocHGlobal(Length);
			Marshal.StructureToPtr(LimitInformation, LimitInformationPtr, false);

			if(SetInformationJobObject(JobHandle, JobObjectExtendedLimitInformation, LimitInformationPtr, Length) == 0)
			{
				throw new Win32Exception();
			}

			// Create the child process
			IntPtr EnvironmentBlock = IntPtr.Zero;
			SafeFileHandle StdInRead = null;
			SafeFileHandle StdOutWrite = null;
			SafeWaitHandle StdErrWrite = null;
			try
			{
				// Create stdin and stdout pipes for the child process. We'll close the handles for the child process' ends after it's been created.
				SECURITY_ATTRIBUTES SecurityAttributes = new SECURITY_ATTRIBUTES();
				SecurityAttributes.bInheritHandle = 1;

				if(CreatePipe(out StdInRead, out StdInWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdInWrite, HANDLE_FLAG_INHERIT, 0) == 0)
				{
					throw new Win32Exception();
				}
				if(CreatePipe(out StdOutRead, out StdOutWrite, SecurityAttributes, 0) == 0 || SetHandleInformation(StdOutRead, HANDLE_FLAG_INHERIT, 0) == 0)
				{
					throw new Win32Exception();
				}
				if(DuplicateHandle(GetCurrentProcess(), StdOutWrite, GetCurrentProcess(), out StdErrWrite, DUPLICATE_SAME_ACCESS, true, 0) == 0)
				{
					throw new Win32Exception();
				}

				// Create the environment block for the child process, if necessary.
				if(Environment != null)
				{
					// The native format for the environment block is a sequence of null terminated strings with a final null terminator.
					List<byte> EnvironmentBytes = new List<byte>();
					foreach(KeyValuePair<string, string> Pair in Environment)
					{
						EnvironmentBytes.AddRange(Encoding.UTF8.GetBytes(Pair.Key));
						EnvironmentBytes.Add((byte)'=');
						EnvironmentBytes.AddRange(Encoding.UTF8.GetBytes(Pair.Value));
						EnvironmentBytes.Add((byte)0);
					}
					EnvironmentBytes.Add((byte)0);

					// Allocate an unmanaged block of memory to store it.
					EnvironmentBlock = Marshal.AllocHGlobal(EnvironmentBytes.Count);
					Marshal.Copy(EnvironmentBytes.ToArray(), 0, EnvironmentBlock, EnvironmentBytes.Count);
				}

				// Set the startup parameters for the new process
				STARTUPINFO StartupInfo = new STARTUPINFO();
                StartupInfo.cb = Marshal.SizeOf(StartupInfo);
				StartupInfo.hStdInput = StdInRead;
				StartupInfo.hStdOutput = StdOutWrite;
				StartupInfo.hStdError = StdErrWrite;
				StartupInfo.dwFlags = STARTF_USESTDHANDLES;

				PROCESS_INFORMATION ProcessInfo = new PROCESS_INFORMATION();
				try
				{
					// Get the flags to create the new process
					ProcessCreationFlags Flags = ProcessCreationFlags.CREATE_NO_WINDOW | ProcessCreationFlags.CREATE_SUSPENDED | ProcessCreationFlags.CREATE_BREAKAWAY_FROM_JOB;
					switch(Priority)
					{
						case ManagedProcessPriority.BelowNormal:
							Flags |= ProcessCreationFlags.BELOW_NORMAL_PRIORITY_CLASS;
							break;
						case ManagedProcessPriority.Normal:
							Flags |= ProcessCreationFlags.NORMAL_PRIORITY_CLASS;
							break;
						case ManagedProcessPriority.AboveNormal:
							Flags |= ProcessCreationFlags.ABOVE_NORMAL_PRIORITY_CLASS;
							break;
					}

					// Create the new process as suspended, so we can modify it before it starts executing (and potentially preempting us)
					if(CreateProcess(null, new StringBuilder("\"" + FileName + "\" " + CommandLine), IntPtr.Zero, IntPtr.Zero, true, Flags, EnvironmentBlock, WorkingDirectory, StartupInfo, ProcessInfo) == 0)
					{
						throw new Win32Exception();
					}

					// Add it to our job object
					if(AssignProcessToJobObject(JobHandle, ProcessInfo.hProcess) == 0)
					{
						throw new Win32Exception();
					}

					// Allow the thread to start running
					if(ResumeThread(ProcessInfo.hThread) == -1)
					{
						throw new Win32Exception();
					}

					// If we have any input text, write it to stdin now
					using(StreamWriter StdInWriter = new StreamWriter(new FileStream(StdInWrite, FileAccess.Write, 4096, false), Console.InputEncoding, 4096))
					{
						if(!String.IsNullOrEmpty(Input))
						{
							StdInWriter.WriteLine(Input);
							StdInWriter.Flush();
						}
					}

					// Create the stream objects for reading the process output
					InnerStream = new FileStream(StdOutRead, FileAccess.Read, 4096, false);
					ReadStream = new StreamReader(InnerStream, Console.OutputEncoding);

					// Wrap the process handle in a SafeFileHandle
					ProcessHandle = new SafeFileHandle(ProcessInfo.hProcess, true);
				}
				finally
				{
					if(ProcessInfo.hProcess != IntPtr.Zero && ProcessHandle == null)
					{
						CloseHandle(ProcessInfo.hProcess);
					}
					if(ProcessInfo.hThread != IntPtr.Zero)
					{
						CloseHandle(ProcessInfo.hThread);
					}
				}
			}
			finally
			{
				if(EnvironmentBlock != IntPtr.Zero)
				{
					Marshal.FreeHGlobal(EnvironmentBlock);
					EnvironmentBlock = IntPtr.Zero;
				}
				if(StdInRead != null)
				{
					StdInRead.Dispose();
					StdInRead = null;
				}
				if(StdOutWrite != null)
				{
					StdOutWrite.Dispose();
					StdOutWrite = null;
				}
				if(StdErrWrite != null)
				{
					StdErrWrite.Dispose();
					StdErrWrite = null;
				}
			}
		}