첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

■ Process 클래스를 사용해 부모 프로세스 종료시 자식 프로세스를 종료시키는 방법을 보여준다.

TestProject.zip
0.01MB

▶ JobObjectInfoType.cs

namespace TestProject;

/// <summary>
/// 작업 객체 정보 타입
/// </summary>
public enum JobObjectInformationType
{
    /// <summary>
    /// Associate Completion Port Information
    /// </summary>
    AssociateCompletionPortInformation = 7,

    /// <summary>
    /// Basic Limit Information
    /// </summary>
    BasicLimitInformation = 2,

    /// <summary>
    /// Basic UI Restrictions
    /// </summary>
    BasicUIRestrictions = 4,

    /// <summary>
    /// End Of Job Time Information
    /// </summary>
    EndOfJobTimeInformation = 6,

    /// <summary>
    /// Extended Limit Information
    /// </summary>
    ExtendedLimitInformation = 9,

    /// <summary>
    /// Security Limit Information
    /// </summary>
    SecurityLimitInformation = 5,

    /// <summary>
    /// Group Information
    /// </summary>
    GroupInformation = 11
}

 

▶ JobObjectLimit.cs

namespace TestProject;

/// <summary>
/// 작업 객체 제한
/// </summary>
[Flags]
public enum JobObjectLimit : uint
{
    /// <summary>
    /// Job Object Limit Kill On Job Close
    /// </summary>
    JobObjectLimitKillOnJobClose = 0x2000
}

 

▶ IO_COUNTERS.cs

using System.Runtime.InteropServices;

namespace TestProject;

/// <summary>
/// IO 카운트
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct IO_COUNTERS
{
    //////////////////////////////////////////////////////////////////////////////////////////////////// Field
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region Field

    /// <summary>
    /// 읽기 연산 카운트
    /// </summary>
    public ulong ReadOperationCount;

    /// <summary>
    /// 쓰기 연산 카운트
    /// </summary>
    public ulong WriteOperationCount;

    /// <summary>
    /// 기타 연산 카운트
    /// </summary>
    public ulong OtherOperationCount;

    /// <summary>
    /// 읽기 전송 카운트
    /// </summary>
    public ulong ReadTransferCount;

    /// <summary>
    /// 쓰기 전송 카운트
    /// </summary>
    public ulong WriteTransferCount;

    /// <summary>
    /// 기타 전송 카운트
    /// </summary>
    public ulong OtherTransferCount;

    #endregion
}

 

▶ JOB_OBJECT_BASIC_LIMIT_INFORMATION.cs

using System.Runtime.InteropServices;

namespace TestProject;

/// <summary>
/// 작업 객체 기본 제한 정보
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct JOB_OBJECT_BASIC_LIMIT_INFORMATION
{
    //////////////////////////////////////////////////////////////////////////////////////////////////// Field
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region Field

    /// <summary>
    /// 프로세스당 사용자 시간 제한
    /// </summary>
    public long PerProcessUserTimeLimit;

    /// <summary>
    /// 작업당 사용자 시간 제한
    /// </summary>
    public long PerJobUserTimeLimit;

    /// <summary>
    /// 제한 플래그
    /// </summary>
    public JobObjectLimit LimitFlags;

    /// <summary>
    /// 최소 작업 세트 크기
    /// </summary>
    public UIntPtr MinimumWorkingSetSize;

    /// <summary>
    /// 최대 작업 세트 크기
    /// </summary>
    public UIntPtr MaximumWorkingSetSize;

    /// <summary>
    /// 액티브 프로세스 제한
    /// </summary>
    public uint ActiveProcessLimit;

    /// <summary>
    /// 친화도
    /// </summary>
    public long Affinity;

    /// <summary>
    /// 우선 순위 클래스
    /// </summary>
    public uint PriorityClass;

    /// <summary>
    /// 스케쥴링 클래스
    /// </summary>
    public uint SchedulingClass;

    #endregion
}

 

▶ JOB_OBJECT_EXTENDED_LIMIT_INFORMATION.cs

using System.Runtime.InteropServices;

namespace TestProject;

/// <summary>
/// 작업 객체 확장 제한 정보
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct JOB_OBJECT_EXTENDED_LIMIT_INFORMATION
{
    //////////////////////////////////////////////////////////////////////////////////////////////////// Field
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region Field

    /// <summary>
    /// 기본 제한 정보
    /// </summary>
    public JOB_OBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;

    /// <summary>
    /// IO 정보
    /// </summary>
    public IO_COUNTERS IOInformation;

    /// <summary>
    /// 프로세스 메모리 제한
    /// </summary>
    public UIntPtr ProcessMemoryLimit;

    /// <summary>
    /// 작업 메모리 제한
    /// </summary>
    public UIntPtr JobMemoryLimit;

    /// <summary>
    /// 피크 프로세스 사용 메모리
    /// </summary>
    public UIntPtr PeakProcessMemoryUsed;

    /// <summary>
    /// 피크 작업 사용 메모리
    /// </summary>
    public UIntPtr PeakJobMemoryUsed;

    #endregion
}

 

▶ SECURITY_ATTRIBUTES.cs

using System.Runtime.InteropServices;

namespace TestProject;

/// <summary>
/// 보안 특성
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
    //////////////////////////////////////////////////////////////////////////////////////////////////// Field
    ////////////////////////////////////////////////////////////////////////////////////////// Public

    #region Field

    /// <summary>
    /// 길이
    /// </summary>
    public int Length;

    /// <summary>
    /// 보안 설명자
    /// </summary>
    public IntPtr SecurityDescriptor;

    /// <summary>
    /// 상속 핸들
    /// </summary>
    public int InheritHandle;

    #endregion
}

 

▶ ChildProcessTracker.cs

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

namespace TestProject;

/// <summary>
/// 자식 프로세스 추적자
/// </summary>
public static class ChildProcessTracker
{
    //////////////////////////////////////////////////////////////////////////////////////////////////// Import
    ////////////////////////////////////////////////////////////////////////////////////////// Static
    //////////////////////////////////////////////////////////////////////////////// Private

    #region 작업 객체 생성하기 - CreateJobObject(jobAttributesHandle, name)

    /// <summary>
    /// 작업 객체 생성하기
    /// </summary>
    /// <param name="jobAttributesHandle">작업 특성 핸들</param>
    /// <param name="name">명칭</param>
    /// <returns>작업 핸들</returns>
    [DllImport("kernel32", CharSet = CharSet.Unicode)]
    private static extern IntPtr CreateJobObject(IntPtr jobAttributesHandle, string name);

    #endregion
    #region 작업 객체 정보 설정하기 - SetInformationJobObject(jobHandle, jobObjectInformationType, jobObjectInformationHandle, jobObjectInformationLength)

    /// <summary>
    /// 작업 객체 정보 설정하기
    /// </summary>
    /// <param name="jobHandle">작업 핸들</param>
    /// <param name="jobObjectInformationType">작업 객체 정보 타입</param>
    /// <param name="jobObjectInformationHandle">작업 객체 정보 핸들</param>
    /// <param name="jobObjectInformationLength">작업 객체 정보 길이</param>
    /// <returns>처리 결과</returns>
    [DllImport("kernel32")]
    private static extern bool SetInformationJobObject
    (
        IntPtr                   jobHandle,
        JobObjectInformationType jobObjectInformationType,
        IntPtr                   jobObjectInformationHandle,
        uint                     jobObjectInformationLength
    );

    #endregion
    #region 작업 객체에 프로세스 할당하기 - AssignProcessToJobObject(jobHandle, processHandle)

    /// <summary>
    /// 작업 객체에 프로세스 할당하기
    /// </summary>
    /// <param name="jobHandle">작업 핸들</param>
    /// <param name="processHandle">프로세스 핸들</param>
    /// <returns>처리 결과</returns>
    [DllImport("kernel32", SetLastError = true)]
    private static extern bool AssignProcessToJobObject(IntPtr jobHandle, IntPtr processHandle);

    #endregion

    //////////////////////////////////////////////////////////////////////////////////////////////////// Import
    ////////////////////////////////////////////////////////////////////////////////////////// Static
    //////////////////////////////////////////////////////////////////////////////// Private

    #region Field

    /// <summary>
    /// 작업 핸들
    /// </summary>
    private static readonly IntPtr _jobHandle;

    #endregion

    //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
    ////////////////////////////////////////////////////////////////////////////////////////// Static

    #region 생성자 - ChildProcessTracker()

    /// <summary>
    /// 생성자
    /// </summary>
    static ChildProcessTracker()
    {
        if(Environment.OSVersion.Version < new Version(6, 2))
        {
            return;
        }

        string jobName = $"ChildProcessTracker{Process.GetCurrentProcess().Id}";

        _jobHandle = CreateJobObject(IntPtr.Zero, jobName);

        JOB_OBJECT_BASIC_LIMIT_INFORMATION jobObjectBasicLimitInformation = new JOB_OBJECT_BASIC_LIMIT_INFORMATION();

        jobObjectBasicLimitInformation.LimitFlags = JobObjectLimit.JobObjectLimitKillOnJobClose;

        JOB_OBJECT_EXTENDED_LIMIT_INFORMATION jobObjectExtendedLimitInformation = new JOB_OBJECT_EXTENDED_LIMIT_INFORMATION();

        jobObjectExtendedLimitInformation.BasicLimitInformation = jobObjectBasicLimitInformation;

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

        IntPtr jobObjectInformationHandle = Marshal.AllocHGlobal(length);

        try
        {
            Marshal.StructureToPtr(jobObjectExtendedLimitInformation, jobObjectInformationHandle, false);

            if(!SetInformationJobObject(_jobHandle, JobObjectInformationType.ExtendedLimitInformation, jobObjectInformationHandle, (uint)length))
            {
                throw new Win32Exception();
            }
        }
        finally
        {
            Marshal.FreeHGlobal(jobObjectInformationHandle);
        }
    }

    #endregion

    //////////////////////////////////////////////////////////////////////////////////////////////////// Method
    ////////////////////////////////////////////////////////////////////////////////////////// Static
    //////////////////////////////////////////////////////////////////////////////// Public

    #region 프로세스 추가하기 - AddProcess(process)

    /// <summary>
    /// 프로세스 추가하기
    /// </summary>
    /// <param name="process">프로세스</param>
    public static void AddProcess(Process process)
    {
        if(_jobHandle != IntPtr.Zero)
        {
            bool success = AssignProcessToJobObject(_jobHandle, process.Handle);

            if(!success && !process.HasExited)
            {
                throw new Win32Exception();
            }
        }
    }

    #endregion
}

 

▶ Program.cs

using System.Diagnostics;

namespace TestProject;

/// <summary>
/// 프로그램
/// </summary>
class Program
{
    //////////////////////////////////////////////////////////////////////////////////////////////////// Method
    ////////////////////////////////////////////////////////////////////////////////////////// Static
    //////////////////////////////////////////////////////////////////////////////// Private

    #region 프로그램 시작하기 - Main()

    /// <summary>
    /// 프로그램 시작하기
    /// </summary>
    private static void Main()
    {
        Process childProcess = Process.Start("notepad.exe");

        ChildProcessTracker.AddProcess(childProcess);

        Console.WriteLine("프로그램을 종료하기 위해서 아무 키나 눌러 주시기 바랍니다.");

        Console.ReadKey(false);
    }

    #endregion
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요