Написать DEMO программу для работы с CreateJobObject/ JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE - C#
Формулировка задачи:
Нужно написать программу, которая демонстрирует работу CreateJobObject/ JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE .
И программа должна запускать калькулятор,если убить процесс нашей программы (с диспетчера например), то дочерный процесс тоже должен закрыватся.
пс. пример должен быть простым и понятным, чтобы такие как я, не мучались..
в этой теме Пример работы с JobObject тоже пытались сделать, что то подобное, но у меня c этим примером не закрывается калькулятор.
И с этими примерами, тоже ничего не получается у меня:
https://searchcode.com/codesearch/view/28089595/
https://code.google.com/p/managed-lz...Process.cs?r=3
http://stackoverflow.com/questions/6...pinvoke-in-net
Не кидать камнями..
Спасибо!
Решение задачи: «Написать DEMO программу для работы с CreateJobObject/ JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE»
textual
Листинг программы
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace JobKillProcess
{
class Program
{
#region ~ Platform Invoke ~
#region ~ Enums ~
private enum JobObjectInfoClass
{
JobObjectExtendedLimitInformation = 9,
}
[Flags]
private enum LimitFlags
{
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x00002000,
}
#endregion
#region ~ Structures ~
/// <summary>
/// [url]https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms684147%28v=vs.85%29.aspx[/url]
/// </summary>
private struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
internal long PerProcessUserTimeLimit;
internal long PerJobUserTimeLimit;
internal LimitFlags LimitFlags;
internal IntPtr MinimumWorkingSetSize;
internal IntPtr MaximumWorkingSetSize;
internal uint ActiveProcessLimit;
internal UIntPtr Affinity;
internal uint PriorityClass;
internal uint SchedulingClass;
}
/// <summary>
/// [url]https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms684125%28v=vs.85%29.aspx[/url]
/// </summary>
private struct IO_COUNTERS
{
internal ulong ReadOperationCount;
internal ulong WriteOperationCount;
internal ulong OtherOperationCount;
internal ulong ReadTransferCount;
internal ulong WriteTransferCount;
internal ulong OtherTransferCount;
}
/// <summary>
/// [url]https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms684156%28v=vs.85%29.aspx[/url]
/// </summary>
private struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
internal JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
internal IO_COUNTERS IoInfo;
internal IntPtr ProcessMemoryLimit;
internal IntPtr JobMemoryLimit;
internal IntPtr PeakProcessMemoryUsed;
internal IntPtr PeakJobMemoryUsed;
}
/// <summary>
/// [url]https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331%28v=vs.85%29.aspx[/url]
/// </summary>
private struct STARTUPINFO
{
internal int cb;
internal IntPtr lpReserved; // Используем IntPtr взамен string, чтобы избежать ненужного преобразования данных
internal IntPtr lpDesktop; // Используем IntPtr взамен string, чтобы избежать ненужного преобразования данных
internal IntPtr lpTitle; // Используем IntPtr взамен string, чтобы избежать ненужного преобразования данных
internal int dwX;
internal int dwY;
internal int dwXSize;
internal int dwYSize;
internal int dwXCountChars;
internal int dwYCountChars;
internal uint dwFillAttribute;
internal uint dwFlags;
internal ushort wShowWindow;
internal ushort cbReserved2;
internal IntPtr lpReserved2;
internal IntPtr hStdInput;
internal IntPtr hStdOutput;
internal IntPtr hStdError;
}
/// <summary>
/// [url]https://msdn.microsoft.com/en-us/library/windows/desktop/ms684873%28v=vs.85%29.aspx[/url]
/// </summary>
private struct PROCESS_INFORMATION
{
internal IntPtr hProcess;
internal IntPtr hThread;
internal int dwProcessId;
internal int dwThreadId;
}
#endregion
#region ~ Kernel32 functions ~
private const string Kernel32Lib = "kernel32.dll";
/// <summary>
/// [url]https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms682409%28v=vs.85%29.aspx[/url]
/// </summary>
/// <param name="lpJobAttributes"></param>
/// <param name="lpName"></param>
/// <returns></returns>
[DllImport(Kernel32Lib, SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr CreateJobObject(
IntPtr lpJobAttributes,
string lpName
);
/// <summary>
/// [url]https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms681949%28v=vs.85%29.aspx[/url]
/// </summary>
/// <param name="hJob"></param>
/// <param name="hProcess"></param>
/// <returns></returns>
[DllImport(Kernel32Lib, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool AssignProcessToJobObject(
IntPtr hJob,
IntPtr hProcess
);
/// <summary>
/// [url]https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms686216%28v=vs.85%29.aspx[/url]
/// </summary>
/// <param name="hJob"></param>
/// <param name="JobObjectInfoClass"></param>
/// <param name="lpJobObjectInfo"></param>
/// <param name="cbJobObjectInfoLength"></param>
/// <returns></returns>
[DllImport(Kernel32Lib, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetInformationJobObject(
IntPtr hJob,
JobObjectInfoClass JobObjectInfoClass,
// Используем ExtendedLimitInformation, т.к. того требует JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
ref JOBOBJECT_EXTENDED_LIMIT_INFORMATION lpJobObjectInfo,
int cbJobObjectInfoLength
);
/// <summary>
/// [url]https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx[/url]
/// </summary>
/// <param name="lpApplicationName"></param>
/// <param name="lpCommandLine"></param>
/// <param name="lpProcessAttributes"></param>
/// <param name="lpThreadAttributes"></param>
/// <param name="bInheritHandles"></param>
/// <param name="dwCreationFlags"></param>
/// <param name="lpEnvironment"></param>
/// <param name="lpCurrentDirectory"></param>
/// <param name="lpStartupInfo"></param>
/// <param name="lpProcessInformation"></param>
/// <returns></returns>
[DllImport(Kernel32Lib, SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CreateProcess(
string lpApplicationName,
string lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
[MarshalAs(UnmanagedType.Bool)] bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
string lpCurrentDirectory,
ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation
);
/// <summary>
/// [url]https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms724211%28v=vs.85%29.aspx[/url]
/// </summary>
/// <param name="hObject"></param>
/// <returns></returns>
[DllImport(Kernel32Lib, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(
IntPtr hObject
);
#endregion
#endregion
static void Main()
{
// Флаг показывающий что процесс создан успешно
var processCreated = false;
var pi = default(PROCESS_INFORMATION);
var hJob = IntPtr.Zero;
try
{
// Создаём процесс калькулятора
var si = new STARTUPINFO();
// cb - обязательное поле, отвечает за размер передаваемой структуры
si.cb = Marshal.SizeOf(si);
bool result = CreateProcess(
null, "calc.exe", IntPtr.Zero, IntPtr.Zero,
false, 0, IntPtr.Zero, null, ref si, out pi);
if (!result)
// Ничего не передаём, исключение должно само корректно получить номер ошибки (Marshal.GetLastWin32Error)
throw new Win32Exception();
processCreated = true;
// Создаём безымянную работу с дефолтными настройками безопасности
hJob = CreateJobObject(IntPtr.Zero, null);
if (hJob == IntPtr.Zero)
throw new Win32Exception();
// Задаём ограничения для работы
var limitInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
limitInfo.BasicLimitInformation.LimitFlags = LimitFlags.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
result = SetInformationJobObject(
hJob, JobObjectInfoClass.JobObjectExtendedLimitInformation,
ref limitInfo, Marshal.SizeOf(limitInfo));
if (!result)
throw new Win32Exception();
// Привязываем процесс калькулятора к работе
if (!AssignProcessToJobObject(hJob, pi.hProcess))
throw new Win32Exception();
Console.WriteLine("Enter any key to exit...");
Console.ReadKey();
}
catch (Win32Exception ex)
{
Console.WriteLine("Error: {0} (code: {1})", ex.Message, ex.ErrorCode);
Console.ReadKey();
}
finally
{
// Закрываем предоставленные системой ресусры: дескрипторы потока и процесса
if (processCreated)
{
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
// Завершаем работу корректно
if (hJob != IntPtr.Zero)
CloseHandle(hJob);
}
}
}
}