Pergunta

Em C++ o aplicativo do Windows, que eu lançar vários longo execução de processos filho (atualmente eu uso CreateProcess(...) para fazer isso.

Eu quero a criança processa a ser fechada automaticamente se o meu processos principais falhas ou é fechada.

Devido a exigência de que esta necessita para trabalhar de uma falha do "pai", eu acredito que isso precisa ser feito usando alguma API/recurso do sistema operacional.De modo que todas as "crianças" os processos são limpos.

Como eu faço isso?

Foi útil?

Solução

A API do Windows oferece suporte a objetos chamados "Objetos de Trabalho".O seguinte código vai criar um "trabalho" que está configurado para encerrar todos os processos quando a aplicação termina (quando suas alças são limpos).Este código deve ser executado somente uma vez.:

HANDLE ghJob = CreateJobObject( NULL, NULL); // GLOBAL
if( ghJob == NULL)
{
    ::MessageBox( 0, "Could not create job object", "TEST", MB_OK);
}
else
{
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };

    // Configure all child processes associated with the job to terminate when the
    jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
    if( 0 == SetInformationJobObject( ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
    {
        ::MessageBox( 0, "Could not SetInformationJobObject", "TEST", MB_OK);
    }
}

Em seguida, quando cada processo filho é criado, execute o seguinte código para o lançamento de cada criança, de cada processo e adicioná-lo para o objeto de trabalho:

STARTUPINFO info={sizeof(info)};
PROCESS_INFORMATION processInfo;

// Launch child process - example is notepad.exe
if (::CreateProcess( NULL, "notepad.exe", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
    ::MessageBox( 0, "CreateProcess succeeded.", "TEST", MB_OK);
    if(ghJob)
    {
        if(0 == AssignProcessToJobObject( ghJob, processInfo.hProcess))
        {
            ::MessageBox( 0, "Could not AssignProcessToObject", "TEST", MB_OK);
        }
    }

    // Can we free handles now? Not sure about this.
    //CloseHandle(processInfo.hProcess); 
    CloseHandle(processInfo.hThread);
}

VISTA NOTA:Ver AssignProcessToJobObject sempre o retorno de "acesso negado" no Vista se você encontrar acesso negado problemas com AssignProcessToObject() na vista.

Outras dicas

Um pouco hackish solução seria o pai para anexar ao processo de cada criança como um depurador (uso DebugActiveProcess).Quando um depurador termina todos os seus depuração de processos são terminados bem.

Uma solução melhor (supondo que você escreveu o filho de processos bem) seria a de ter o filho de processos de monitorar o pai e sair se vai embora.

Windows Objetos de Trabalho soa como um bom lugar para começar.O nome do Objeto de Trabalho teria de ser bem conhecido, ou passados para os filhos (ou herdar a alça).Os filhos precisam perceber quando o pai morre, através de uma falha IPC de "pulsação" ou apenas WFMO/WFSO no percentual identificador de processo.Em um ponto em que qualquer criança poderia TermianteJobObject para trazer para baixo a todo o grupo.

Você pode manter uma vigilância separado do processo de execução.A sua tarefa será apenas assistindo o atual espaço de processo para detectar situações como a que você descreve.Ele poderia até mesmo re-lançar o aplicativo original, depois de uma queda ou de fornecer diferentes opções para o usuário, coletar informações de depuração, etc.Apenas tente manter simples o suficiente para que você não precisa de um segundo cão de guarda para assistir o primeiro.

Você provavelmente terá que manter uma lista de processos de você iniciar, e matá-los um por um quando sair do programa.Eu não tenho certeza de que os detalhes de como fazer isso em C++ mas não deve ser difícil.A parte mais difícil seria, provavelmente, garantindo que a criança, processos de desligamento, no caso de uma falha de aplicativo..Net tem a capacidade para adicionar uma função que é chamada quando ocorre uma exceção não tratada.Eu não tenho certeza se o C++ oferece as mesmas capacidades.

Você pode encapsular cada processo em um objeto C++ e manter uma lista deles em âmbito global.Os destruidores pode encerrar cada processo.Que irá funcionar bem se o programa sai normalmente, mas ele falha, todas as apostas estão fora.

Aqui está um exemplo grosseiro:

class myprocess
{
public:
    myprocess(HANDLE hProcess)
        : _hProcess(hProcess)
    { }

    ~myprocess()
    {
        TerminateProcess(_hProcess, 0);
    }

private:
    HANDLE _hProcess;
};

std::list<myprocess> allprocesses;

Em seguida, sempre que você iniciar uma, chamada allprocessess.push_back(hProcess);

Apenas em cima da minha cabeça:

  • Você já considerou o uso de threads em vez de processos?
  • Tente passar o identificador do thread principal/processo para os processos filhos e levá-los a esperar que a alça.Isso funciona para threads, como à espera de um identificador de thread espera até que a thread concluir e sai.Não sabe se ele vai trabalhar para processos, deve confira MSDN para verificar isso.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top