728x90
반응형
728x170
■ Process 클래스를 사용해 부모 프로세스 종료시 자식 프로세스를 종료시키는 방법을 보여준다.
▶ 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
반응형
그리드형(광고전용)
'C# > Common' 카테고리의 다른 글
[C#/COMMON] RTF 파서 사용하기 (0) | 2022.11.03 |
---|---|
[C#/COMMON/.NET6] Stream 클래스 : CopyTo 메소드를 사용해 스트림에서 바이트 배열 구하기 (0) | 2022.10.24 |
[C#/COMMON/.NET6] MemoryStream 클래스 : Write 메소드를 사용해 스트림에서 바이트 배열 구하기 (0) | 2022.10.24 |
[C#/COMMON/.NET6] DateTime 구조체 : ParseExact 정적 메소드를 사용해 ISO 8601 날짜 포맷 문자열에서 DateTime 객체 구하기 (0) | 2022.10.24 |
[C#/COMMON/.NET6] DateTime 구조체 : Parse 정적 메소드를 사용해 ISO 8601 날짜 포맷 문자열에서 DateTime 객체 구하기 (0) | 2022.10.24 |
[C#/COMMON/.NET6] Uri 클래스 : Host 속성을 사용해 도메인 호스트 구하기 (0) | 2022.10.23 |
[C#/COMMON] Directory 클래스 : GetAccessControl 정적 메소드를 사용해 디렉토리 쓰기 권한 체크하기 (0) | 2022.10.23 |
[C#/COMMON] Directory 클래스 : GetAccessControl 정적 메소드를 사용해 디렉토리 권한 체크하기 (0) | 2022.10.23 |
[C#/COMMON/.NET6] File 클래스 : Create 정적 메소드를 사용해 디렉토리 쓰기 가능 여부 구하기 (0) | 2022.10.23 |
[C#/COMMON/.NET6] 64비트 운영 체제 여부 구하기 (0) | 2022.10.22 |
댓글을 달아 주세요