Home >Backend Development >C++ >How to Use P/Invoke to Create and Manage Job Objects in C# to Ensure Process Termination?

How to Use P/Invoke to Create and Manage Job Objects in C# to Ensure Process Termination?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2025-01-04 01:54:38750browse

How to Use P/Invoke to Create and Manage Job Objects in C# to Ensure Process Termination?

Example Implementation of CreateJobObject and SetInformationJobObject Using P/Invoke

This example demonstrates how to create a job object (CreateJobObject) and set its basic limit information (SetInformationJobObject) to ensure that processes associated with the job terminate when the job is closed.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace JobObjectPInvoke
{
    class Program
    {
        const int JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000;

        [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 CloseHandle(IntPtr hObject);

        static void Main()
        {
            // Get a handle to the current process.
            IntPtr currentProcessHandle = Process.GetCurrentProcess().Handle;

            // Create a job object.
            IntPtr jobObjectHandle = CreateJobObject(IntPtr.Zero, null);
            if (jobObjectHandle == IntPtr.Zero)
            {
                throw new Exception($"Failed to create job object: {Marshal.GetLastWin32Error()}");
            }

            // Set the limit information for the job object.
            JOBOBJECT_BASIC_LIMIT_INFORMATION jobLimitInfo = new JOBOBJECT_BASIC_LIMIT_INFORMATION
            {
                LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
            };

            int sizeOfJobLimitInfo = Marshal.SizeOf(jobLimitInfo);
            IntPtr ptrJobLimitInfo = Marshal.AllocHGlobal(sizeOfJobLimitInfo);
            Marshal.StructureToPtr(jobLimitInfo, ptrJobLimitInfo, false);

            if (!SetInformationJobObject(jobObjectHandle, JobObjectInfoType.BasicLimitInformation, ptrJobLimitInfo, (uint)sizeOfJobLimitInfo))
            {
                throw new Exception($"Failed to set job limit information: {Marshal.GetLastWin32Error()}");
            }

            // Add the current process to the job object.
            if (!AssignProcessToJobObject(jobObjectHandle, currentProcessHandle))
            {
                throw new Exception($"Failed to add process to job object: {Marshal.GetLastWin32Error()}");
            }

            // Sleep for 10 seconds.
            System.Threading.Thread.Sleep(10000);

            // Close the job object.
            CloseHandle(jobObjectHandle);

            // The current process will terminate when the job object is closed. You can use this example to create a sandbox environment for your processes.
        }

        #region Helper Classes

        [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;
        }

        public enum JobObjectInfoType
        {
            AssociateCompletionPortInformation = 7,
            BasicLimitInformation = 2,
            BasicUIRestrictions = 4,
            EndOfJobTimeInformation = 6,
            ExtendedLimitInformation = 9,
            SecurityLimitInformation = 5
        }

        #endregion
    }
}

This expanded example illustrates a complete implementation of creating a job object, setting its basic limit information, and adding a process to the job object. The JOBOBJECT_LIMIT_KILL_ON_JOB_CLOSE flag ensures that any processes associated with the job will be terminated when the job object is closed, ensuring that all resources used by the processes are cleaned up properly.

The above is the detailed content of How to Use P/Invoke to Create and Manage Job Objects in C# to Ensure Process Termination?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn