Hvordan kan jeg automatisk ødelegge barn prosesser i Windows?

stemmer
58

I C ++ Windows app, lansere jeg flere veletablerte barn prosesser (for tiden jeg bruker CreateProcess (...) for å gjøre dette.

Jeg vil at barn prosesser som skal lukkes automatisk hvis mine hovedprosesser krasjer eller lukkes.

På grunn av kravet om at dette må jobbe for en krasj av foreldre, tror jeg dette måtte gjøres ved hjelp av noen API / funksjon i operativsystemet. Slik at alle barn prosesser er ryddet opp.

Hvordan gjør jeg dette?

Publisert på 09/09/2008 klokken 22:13
kilden bruker
På andre språk...                            


7 svar

stemmer
-2

Du vil sannsynligvis nødt til å holde en liste over prosessene du starter, og drepe dem én etter én når du avslutter programmet. Jeg er ikke sikker på detaljene i å gjøre dette i C ++, men det bør ikke være vanskelig. Den vanskelige delen vil trolig være å sikre at barn prosesser er nedleggelse i tilfelle av et program krasjer. Net har evnen til å legge til en funksjon som får kalles når et ubehandlet unntak oppstår. Jeg er ikke sikker på om C ++ har de samme mulighetene.

Svarte 09/09/2008 kl. 22:19
kilden bruker

stemmer
66

Windows API støtter objekter kalt "Job Objects". Følgende kode vil skape en "jobb" som er konfigurert til å stenge alle prosesser når hovedprogram endene (når håndtakene er ryddet opp). Denne koden skal bare kjøres en gang .:

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);
    }
}

Så når hvert barn prosessen er opprettet, utføre følgende kode for å starte hvert barn hver prosess og legge den til jobben objekt:

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 MERK: Se AssignProcessToJobObject alltid tilbake "ingen tilgang" på Vista hvis du støter adgangsnekt problemer med AssignProcessToObject () på vista.

Svarte 09/09/2008 kl. 22:22
kilden bruker

stemmer
0

Du kan holde en egen vaktbikkje prosessen i gang. Dens eneste oppgave er å se på den nåværende prosessen plass til å få øye på situasjoner som du beskriver. Det kan også re-lansere den opprinnelige søknaden etter en krasj eller gi ulike alternativer for brukeren, samle debug informasjon, etc. Bare prøv å holde det enkelt nok slik at du ikke trenger en andre vaktbikkje for å se den første.

Svarte 09/09/2008 kl. 22:25
kilden bruker

stemmer
5

En noe hackish løsning ville være for den overordnede prosessen for å feste til hvert barn som et feilsøkingsprogram (bruk DebugActiveProcess ). Når et feilsøkingsprogram avslutter alle dens debuggee prosesser er avsluttet i tillegg.

En bedre løsning (forutsatt at du skrev barn prosesser i tillegg) ville være å ha barnet prosesser overvåke foreldre og avslutte hvis det går unna.

Svarte 09/09/2008 kl. 22:28
kilden bruker

stemmer
-2

Du kan kapsle hver prosess i en C ++ objekt og holde en liste over dem i globalt omfang. Destructors kan stenge hver prosess. Det vil fungere fint hvis programmet avsluttes normalt, men det den krasjer, er alle spill av.

Her er en grov eksempel:

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

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

private:
    HANDLE _hProcess;
};

std::list<myprocess> allprocesses;

Så når du starter en kaller allprocessess.push_back (hProcess);

Svarte 09/09/2008 kl. 22:34
kilden bruker

stemmer
-4

Like ved toppen av hodet mitt:

  • Har du vurdert å bruke tråder i stedet for prosesser?
  • Prøv passerer håndtaket på hovedtråden / prosess til barn prosesser og få dem til å vente på at håndtaket. Dette fungerer for tråder, som venter på en tråd håndtak venter til den tråden er fullført og utganger. Ikke så sikker på om det vil fungere for prosesser, bør sjekke ut MSDN for å bekrefte dette.
Svarte 10/09/2008 kl. 02:20
kilden bruker

stemmer
3

Windows Job objekter høres ut som et godt sted å begynne. Navnet på jobb Object må være godt kjent, eller sendes til barna (eller arve håndtaket). Barna må være varsel når foreldrene dør, enten gjennom et mislykket IPC "hjerteslag" eller bare WFMO / WFSO på foreldrenes prosessen håndtak. På det tidspunktet noen barn prosessen kan TermianteJobObject å få ned hele gruppen.

Svarte 10/09/2008 kl. 04:24
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more