Home >Backend Development >C++ >How to Use CreateJobObject and SetInformationJobObject with PInvoke in .NET to Manage Process Termination?

How to Use CreateJobObject and SetInformationJobObject with PInvoke in .NET to Manage Process Termination?

DDD
DDDOriginal
2024-12-27 13:46:10629browse

How to Use CreateJobObject and SetInformationJobObject with PInvoke in .NET to Manage Process Termination?

Working Example of CreateJobObject/SetInformationJobObject PInvoke in .NET

Question:

I've been struggling to create a working example of using the CreateJobObject and SetInformationJobObject methods through PInvoke. Despite various attempts, I'm encountering errors when trying to set the JOBOBJECT_BASIC_LIMIT_INFORMATION using the SetInformationJobObject method.

Answer:

To address your issue, let's delve into the intricacies of working with CreateJobObject and SetInformationJobObject in .NET through PInvoke. Here's a step-by-step guide with a functional example:

1. Create a Job Object:

First, we'll create a job object using the CreateJobObject method. This method takes two arguments: a security attribute and the job name (which we'll leave empty).

IntPtr jobHandle = CreateJobObject( null , null );

2. Add Processes to the Job Object:

Next, we need to assign processes to our newly created job object. The AssignProcessToJobObject method is used for this purpose.

AssignProcessToJobObject( jobHandle , myProcess.Handle );
AssignProcessToJobObject( jobHandle , Process.GetCurrentProcess().Handle );

3. Set Job Limits:

Now, we'll set job limits using the SetInformationJobObject method. We'll specifically focus on setting the JOBOBJECT_LIMIT_KILL_ON_JOB_CLOSE flag.

JOBOBJECT_BASIC_LIMIT_INFORMATION limits = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
limits.LimitFlags = (short)LimitFlags.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
IntPtr pointerToJobLimitInfo = Marshal.AllocHGlobal( Marshal.SizeOf( limits ) );
Marshal.StructureToPtr( limits , pointerToJobLimitInfo , false );   
SetInformationJobObject( job , JOBOBJECTINFOCLASS.JobObjectBasicLimitInformation , pionterToJobLimitInfo ,  ( uint )Marshal.SizeOf( limits ) )

In this code, we've defined the JOBOBJECT_BASIC_LIMIT_INFORMATION structure and set the LimitFlags to JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE. This ensures that when one process in the job object is terminated, the other processes are also automatically terminated.

Complete Code Example:

Here's the complete code example that incorporates these steps:

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

class Program
{
    [DllImport( "kernel32.dll" , EntryPoint = "CreateJobObjectW" , CharSet = CharSet.Unicode )]
    public static extern IntPtr CreateJobObject( IntPtr JobAttributes , string lpName );

    [DllImport( "kernel32.dll" )]
    static extern bool SetInformationJobObject( IntPtr hJob , JOBOBJECTINFOCLASS JobObjectInfoClass , IntPtr lpJobObjectInfo , uint cbJobObjectInfoLength );

    public enum JOBOBJECTINFOCLASS
    {
        JobObjectAssociateCompletionPortInformation = 7 ,
        JobObjectBasicLimitInformation = 2 ,
        JobObjectBasicUIRestrictions = 4 ,
        JobObjectEndOfJobTimeInformation = 6 ,
        JobObjectExtendedLimitInformation = 9 ,
        JobObjectSecurityLimitInformation = 5
    }


    [StructLayout( LayoutKind.Sequential )]
    struct JOBOBJECT_BASIC_LIMIT_INFORMATION
    {
        public Int64 PerProcessUserTimeLimit;
        public Int64 PerJobUserTimeLimit;
        public Int16 LimitFlags;
        public UIntPtr MinimumWorkingSetSize;
        public UIntPtr MaximumWorkingSetSize;
        public Int16 ActiveProcessLimit;
        public Int64 Affinity;
        public Int16 PriorityClass;
        public Int16 SchedulingClass;
    }

    public enum LimitFlags
    {
        JOB_OBJECT_LIMIT_ACTIVE_PROCESS = 0x00000008 ,
        JOB_OBJECT_LIMIT_AFFINITY = 0x00000010 ,
        JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800 ,
        JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION = 0x00000400 ,
        JOB_OBJECT_LIMIT_JOB_MEMORY = 0x00000200 ,
        JOB_OBJECT_LIMIT_JOB_TIME = 0x00000004 ,
        JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x00002000 ,
        JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME = 0x00000040 ,
        JOB_OBJECT_LIMIT_PRIORITY_CLASS = 0x00000020 ,
        JOB_OBJECT_LIMIT_PROCESS_MEMORY = 0x00000100 ,
        JOB_OBJECT_LIMIT_PROCESS_TIME = 0x00000002 ,
        JOB_OBJECT_LIMIT_SCHEDULING_CLASS = 0x00000080 ,
        JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK = 0x00001000 ,
        JOB_OBJECT_LIMIT_WORKINGSET = 0x00000001
    }


    [DllImport( "kernel32.dll" )]
    [return: MarshalAs( UnmanagedType.Bool )]
    static extern bool AssignProcessToJobObject( IntPtr hJob , IntPtr hProcess );

    static void Main( string[] args )
    {
        Process myProcess = // POPULATED SOMEWHERE ELSE

        // Create Job & assign this process and another process to the job
        IntPtr jobHandle = CreateJobObject( null , null );
        AssignProcessToJobObject( jobHandle , myProcess.Handle );
        AssignProcessToJobObject( jobHandle , Process.GetCurrentProcess().Handle );

        // Ensure that killing one process kills the others                
        JOBOBJECT_BASIC_LIMIT_INFORMATION limits = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
        limits.LimitFlags = (short)LimitFlags.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
        IntPtr pointerToJobLimitInfo = Marshal.AllocHGlobal( Marshal.SizeOf( limits ) );
        Marshal.StructureToPtr( limits , pointerToJobLimitInfo , false );   
        SetInformationJobObject( job , JOBOBJECTINFOCLASS.JobObjectBasicLimitInformation , pionterToJobLimitInfo ,  ( uint )Marshal.SizeOf( limits ) )
    }
}

This code will create a job object, add the current process and another process (specified by myProcess) to the job object, and set the JOBOBJECT_LIMIT_KILL_ON_JOB_CLOSE flag. By doing so, when either the current process or the myProcess is terminated, the other process will also be terminated automatically.

The above is the detailed content of How to Use CreateJobObject and SetInformationJobObject with PInvoke in .NET to Manage 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