11
votes

Terminer un arbre de processus (C pour Windows)

Cela a été demandé avant, mais je ne trouve pas de réponse définitive, en code.

J'ouvre un processus, Processa (avec PID 1234). Ce processus ouvre un processus enfant, Processab (PID 5678). Après avoir terminé, je termine le processus, mais j'ai toujours la persistance du processus de traitement.

Comment puis-je mettre fin à l'ensemble de l'arbre de processus? Comment je veux dire, comment puis-je vous assurer que si je termine le processus que j'ai ouvert, je termine également tous les processus associés?

merci

code est apprécié.


0 commentaires

7 Réponses :


-1
votes

Ce qui suit est pour Linux, mais j'espère que cela aide pour Windows avec une certaine adaptation.

Lorsque vous fourchette (), enregistrez la valeur de retour, qui correspond au PID du processus enfant, puis lorsque le parent est sur le point de sortir, tuez () le PID.

Si vous avez plusieurs processus d'enfants, vous pouvez envoyer la victime au groupe de processus. Par défaut, les processus enfants ont le même PGID que le parent.


1 commentaires

1) J'aimerais que je travaillais sur Linux 2) Je souhaite que Windows avait la fourchette () 3) Le processus que j'ouvre ouvrira les processus enfants, donc je n'ai aucun contrôle sur cela, mais merci de toute façon



0
votes

Il y a Comment tuer un arborescence de processus , mais c'est en C #. Je ne pense pas qu'il soit trop difficile de porter cela à c.

voir Fonction NTQUERYInformationProcess et < Un href = "http://msdn.microsoft.com/en-us/library/ms686714%28vs.85%29.aspx" rel = "NOfollow NOREFERRER"> TerminerProcess fonction .


1 commentaires

J'ai essayé de convertir ce code hier mais pas de chance. Quoi qu'il en soit, je suis déjà en train d'utiliser NTQuery et de mettre fin à la propession, mais ceux qui ne prennent soinnent que le parent et non le reste



11
votes

check ce fil pour regrouper les processus dans un «travail».

Si cela ne fonctionne pas pour vous, une approche dominante peut aller comme suit:

  1. Obtenez votre identifiant de processus principal
  2. appelez CreateToolHelP32Snapshot < / a> à énumerAserAll les processus sur le système
  3. Vérifiez le membre Th32ParentProcessid de la structure Processentry32 sur chaque processus, s'il correspond à votre identifiant parent, puis terminez le processus (en utilisant TerminerProcess )
  4. Après la résiliation des enfants, résiliant le processus principal

    échantillon code: xxx


6 commentaires

Je n'arrive pas à l'avoir bien. Avez-vous un échantillon d'extrait? Merci


Désolé, j'avais écrit cela de la mémoire. Le premier appel devrait être CreatoolHelP32Snapshot, pas d'énumprocesses. Échantillon ci-dessus.


Vous devez obtenir des privilèges de débogage pour ouvrir le processus, mais cela semble fonctionner autre chose que cela. Merci


@mjmarsh merci pour cela. Notez que pour l'affaire Homebrew, vous manquez une récursion. J'ai répondu ci-dessous.


Attention, il y a un problème avec ce code car il sera tuer des processus supplémentaires. Windows (au moins XP) recycle des pids assez vite. Vous devez vérifier la date de début des processus que vous avez l'intention de tuer pour vous assurer qu'ils font vraiment partie de l'arbre de processus que vous avez initialement créé.


Le problème de fond ici est que Th32ParentProcessid contiendra le PID du parent, même si ledit parent est déjà mort. Vous devez donc vous assurer que le PID parent n'a pas été réutilisé par un processus ultérieur en comparant les dates de début. Numéro observé sur Windows XP il y a quelques années.



3
votes

Pour tuer un arbre entier avec tout !!! Childs: xxx


1 commentaires

Vous ne pouvez pas appeler GetWindowThreadProcessid avec HWND non défini. Bien que le code démontre définitivement une bonne idée d'essayer de fermer les fenêtres bien, cela ne fonctionne pas.



5
votes

Utilisez Objets de travail .

C'est la chose la plus proche d'un «groupe de processus» Unix que Windows a à offrir.

Les objets d'emploi vous permettent d'indiquer un processus d'enfant (et tous ses enfants) peuvent être gérés ensemble, en particulier pour être tué. Contrairement à Unix, à la suite de cet écriture «Les objets de travail» ne peuvent pas être imbriqués . Ce qui signifie que si un parent crée un objet d'emploi pour un enfant, tous les enfants de cet enfant ne peuvent pas utiliser eux-mêmes des objets de travail (ce qui est / grave / limitation, comme un système de fichiers qui permet uniquement un niveau de sous-répertoires).


1 commentaires

La prise en charge de la nidification des objets de travail a été ajoutée à Windows 8 et Windows Server 2012.



0
votes

@MJMARSH répond aux besoins de récupération de l'affaire Homebrew, sinon c'est le bon. La création d'objets de travail est meilleure que celle ci-dessous lorsque vous le pouvez.

void KillProcessTree(DWORD myprocID)
{
    PROCESSENTRY32 pe;

    memset(&pe, 0, sizeof(PROCESSENTRY32));
    pe.dwSize = sizeof(PROCESSENTRY32);

    HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (::Process32First(hSnap, &pe))
    {
        do // Recursion
        {
            if (pe.th32ParentProcessID == myprocID)
                KillProcessTree(pe.th32ProcessID);
        } while (::Process32Next(hSnap, &pe));
    }


    // kill the main process
    HANDLE hProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, myprocID);

    if (hProc)
    {
        ::TerminateProcess(hProc, 1);
        ::CloseHandle(hProc);
    }
}


1 commentaires

Même problème ici, puisque Windows (au moins XP) recycle des PIDS assez rapidement, vous devez être très prudent de ne pas tuer des processus non liés. Ces API signaleront des PPID pour de longs processus morts dont les PID peuvent avoir été recyclés. Vérifiez la date de début des parents pour vous assurer qu'elle est liée aux processus que vous avez engendrés.



0
votes

Pure C Approche très rapide et sale: Utilisez Système () Code> avec Taskkill.exe CODE>

/* Kill process tree in C on windows: quick and very dirty solution */
void killtree(DWORD pid, char force, char tree) {
  char cmd[1024];
  char *forceflag = force ? " /F" : "";
  char *treeflag = tree ? " /T" : "";
  sprintf(cmd, "taskkill%s%s /PID %lu", forceflag, treeflag, pid);
  system(cmd);

  /* optional additional code-- see below */
  if(process_is_running(pid)) {
    fprintf(errlog, "couldn't kill %lu\r\n", pid);
    fflush(errlog);
  }
}

/* if you want, you might also want to use process_is_running() */
static char process_is_running(DWORD pid) {
  if(!pid)
    return 0;
  HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, pid);
  DWORD ret = WaitForSingleObject(process, 0);
  CloseHandle(process);
  return ret == WAIT_TIMEOUT;
}


0 commentaires