How to find list of JobObjects that are assigned to the current process?

109 Views Asked by At

I'm running a program in C#, and I want to know the list of JobObjects that are assigned to the current process. Is there a way to do this?

To be more specific about my use-case, I'm trying to find the memory limit of the current process. The problem is that the function that returns the limits, returns the limits of the last one. So, if 1 JobObject is assigned to the current process, it is simple, but otherwise I don't understand how do it. It is demonstrated in the example below:

    [DllImport("kernel32.dll", SetLastError = true), SuppressUnmanagedCodeSecurity]
    public static extern IntPtr CreateJobObjectW(IntPtr securityAttrs, [MarshalAs(UnmanagedType.LPWStr)] string name);


    [DllImport("kernel32.dll", SetLastError = true), SuppressUnmanagedCodeSecurity]
    public static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);

    [DllImport("kernel32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool QueryInformationJobObject(IntPtr hJob, JobObjectInfoType infoClass, IntPtr info, UInt32 infoLength, IntPtr returnLength);

    public static IntPtr CreateAndAssignJobObject(string name)
    {
        var jobObjectHandle = CreateJobObjectW(securityAttrs: IntPtr.Zero, name);
        var processHandle = Process.GetCurrentProcess().Handle;
        AssignProcessToJobObject(jobObjectHandle, processHandle);
        return jobObjectHandle;
    }

    public static void LimitJobObjectMemory(IntPtr jobObjectHandle, ulong memoryLimit)
    {
        // Set the memory limit of the JobObject to 'memoryLimit'
    }

    /// <summary>
    /// Gets a struct containing the extended limit information for the job object.
    /// </summary>
    private static JOBOBJECT_EXTENDED_LIMIT_INFORMATION GetExtendedLimitInformation()
    {
        var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
        int infoSize = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
        IntPtr extendedInfoPtr = Marshal.AllocHGlobal(infoSize);

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

            if (!QueryInformationJobObject(
                     IntPtr.Zero,
                     JobObjectInfoType.ExtendedLimitInformation,
                     extendedInfoPtr,
                     (UInt32)infoSize,
                     IntPtr.Zero))
            {
                throw new UtilsException($"QueryInformationJobObject failed; err={Marshal.GetLastWin32Error()}");
            }

            extendedInfo = (JOBOBJECT_EXTENDED_LIMIT_INFORMATION)Marshal.PtrToStructure(extendedInfoPtr, typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
        }
        finally
        {
            Marshal.FreeHGlobal(extendedInfoPtr);
        }

        return extendedInfo;
    }

    public static void Main()
    {
        var job1Handle = CreateAndAssignJobObject("job1");
        LimitJobObjectMemory(job1Handle, 4_000_000_000);

        var job2Handle = CreateAndAssignJobObject("job2");
    }

I'll explain what happens in the code: I create the first JobObject (job1Handle), limit its memory, and then create the second JobObject. Now, when I request the limits of the current process, I get the limits defined in the last JobObject. How can I get an aggregation (minimum, for instance) of the memory limit in all JobObjects of the process? Or more generally, how to enumerate the JobObjects assigned to the process?

0

There are 0 best solutions below