Как оконечные дочерние процессы, когда родительский процесс, завершенный в C#

Задача: Автоматическое уничтожение все дочерние процессы, если оконечный родительский процесс. Родитель procees может быть завершен не только корректным способом, но также и путем уничтожения в ProcessExplorer, например. Как я могу сделать это?

Подобный вопрос в С совете темы использовать объекты Job. Как использовать его в C#, не экспортируя внешний DLL?


Я пытался использовать Объекты Задания. Но этот код не работает правильно:

  var job = PInvoke.CreateJobObject(null, null);
  var jobli = new PInvoke.JOBOBJECT_BASIC_LIMIT_INFORMATION();

  jobli.LimitFlags = PInvoke.LimitFlags.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
                   | PInvoke.LimitFlags.JOB_OBJECT_LIMIT_PRIORITY_CLASS
                   | PInvoke.LimitFlags.JOB_OBJECT_LIMIT_JOB_TIME
                   | PInvoke.LimitFlags.JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION
                   | PInvoke.LimitFlags.JOB_OBJECT_LIMIT_JOB_MEMORY;

  var res = PInvoke.SetInformationJobObject(job, PInvoke.JOBOBJECTINFOCLASS.JobObjectBasicLimitInformation, jobli, 48);

  if (!res)
  {
    int b = PInvoke.GetLastError();
    Console.WriteLine("Error " + b);
  }

  var Prc = Process.Start(...);

  PInvoke.AssignProcessToJobObject(job, Prc.Handle);

PInvoke. SetInformationJobObject возвращается с ошибкой. GetLastError возвращает ошибку 24. Однако PInvoke. Работы AssignProcessToJobObject и дочерний процесс, добавленный к Очереди заданий (я вижу его в ProcessExplorer). Но, потому что PInvoke. SetInformationJobObject не работают - порожденный процесс остается в живых, когда я уничтожаю родительский.

Что я имею неправильными в этом коде?

16
задан Community 23 May 2017 в 12:00
поделиться

3 ответа

Windows не принудительно закрывает дочерние процессы при закрытии родительского процесса. Когда вы выбираете «Убить дерево» в таком инструменте, как диспетчер задач или обозреватель процессов, инструмент фактически находит все дочерние процессы и уничтожает их один за другим.

Если вы хотите убедиться, что дочерние процессы очищаются при завершении вашего приложения, вы можете создать класс ProcessManager, который реализует IDisposable, который фактически создает процессы, отслеживает их экземпляры и вызывает Kill для каждого из них в Dispose, например

public class ProcessManager:IDisposable
{
    List<Process> processes=new List<Process>();

    public Process Start(ProcessStartInfo info)
    {
        var newProcess = Process.Start(info);
        newProcess.EnableRaisingEvents = true
        processes.Add(newProcess);
        newProcess.Exited += (sender, e) => processes.Remove(newProcess);
        return newProcess;
    }

    ~ProcessManager()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        foreach (var process in processes)
        {
            try
            {
                if (!process.HasExited)
                    process.Kill();
            }
            catch{}                    
        }
    }
}
2
ответ дан 30 November 2019 в 21:27
поделиться

Вы можете передать ProcessID родительского процесса в качестве аргумента дочернему процессу. И тогда дочерние процессы будут нести ответственность за то, чтобы время от времени проверять, работает ли родительский процесс. (Вызов Process.GetProcessById .)

Другой способ отслеживать существование родительского процесса - использовать примитив синхронизации Mutex . Родительское приложение изначально создаст глобальный мьютекс с именем, известным детям. Дети могут время от времени проверять, существует ли еще мьютекс, и прекращать работу, если нет. (После закрытия родительского процесса мьютекс будет уничтожен системой автоматически, независимо от способа его закрытия.)

4
ответ дан 30 November 2019 в 21:27
поделиться

Вы обратили внимание на код ошибки? Ошибка 24 - это ERROR_BAD_LENGTH, что, вероятно, означает, что 48 - это неправильная длина структуры. Я думаю, что 44, но вы должны сделать sizeof, чтобы быть уверенным.

3
ответ дан 30 November 2019 в 21:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: