IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo
Sommaire > Processus et threads
        Comment lancer un processus ?
        Comment lancer un processus avec les droits d'un utilisateur (Exécuter en tant que ...) ?
        Comment obtenir un handle vers un processus connaissant son nom ?
        Comment obtenir un handle vers un processus connaissant son PID ?
        Comment ajuster les privilèges d'un processus ?
        Comment obtenir la liste de tous les processus en cours ?
        Comment obtenir la liste de tous les modules chargés par un processus ?
        Que se passe-t-il si je ferme le handle d'un processus ou d'un thread avant que celui-ci s'est terminé ?
        Comment obtenir l'ID du thread (ainsi que celui du processus ayant créé ce thread) ayant créé une fenêtre ?
        Comment obtenir le chemin complet d'un processus ?
        Comment changer le répertoire courant ?



Comment lancer un processus ?
auteur : Melem
L'API CreateProcess permet de créer un nouveau processus en spécifiant le nom ou le chemin de l'exécutable à lancer.
#include <windows.h>

int main()
{
    STARTUPINFO si;         /* Requis par CreateProcess */
    PROCESS_INFORMATION pi; /* Requis par CreateProcess */

    /* La structure si est utilisée en entrée donc elle doit être mpérativement initialisée    */
    ZeroMemory(&si, sizeof(si));

    /* Pas la peine d'initialiser la structure pi car elle sera écrite et non lue              */
    
    if (CreateProcess( "c:\\developpez\\test.exe",       /* Nom de l'exécutable                    */
                       NULL,      /* Arguments de la ligne de commande                             */
                       NULL,      /* Attributs de sécurité du nouveau processus (processus fils)   */
                       NULL,      /* Attributs de sécurité du thread principal                     */
                       FALSE,     /* Le processus fils héritera t-il des handles du processus père */
                       0,         /* Flags de création                                             */
                       NULL,      /* Variables d'environnement                                     */
                       NULL,      /* Répertoire courant                                            */
                       &si,       /* Paramètres d'initialisation du processus                      */
                       &pi        /* Informations sur le processus                                 */ ))
    {
        WaitForSingleObject(pi.hProcess, INFINITE);      /* Attendre la fin du processus           */
    
        CloseHandle(pi.hProcess); /* Fermer le handle vers le processus                            */
        CloseHandle(pi.hThread);  /* Fermer le handle vers le thread principal du processus        */
    }

    return 0;
}

L'API ShellExecute permet d'ouvrir un fichier (pas nécessairement un exe) ou un dossier exactement comme si on avait double-cliqué sur ce fichier ou dossier depuis l'explorateur. D'autres actions, par exemple imprimer (si le document est imprimable), sont également possibles.
#include <windows.h>

int main()
{
    ShellExecute( NULL,                       /* Fenêtre parent                    */
                  "open",                     /* Action à faire                    */
                  "c:\\developpez\\test.exe", /* Nom du fichier                    */
                  NULL,                       /* Arguments de la ligne de commande */
                  NULL,                       /* Répertoire courant                */
                  SW_SHOWNORMAL               /* Comment afficher la fenêtre       */ );

    return 0;
}

ShellExecute exécute l'opération demandée et retourne immédiatement. Pour plus de contrôle, utilisez ShellExecuteEx.


Comment lancer un processus avec les droits d'un utilisateur (Exécuter en tant que ...) ?
auteur : Melem
Le plus simple est d'utiliser CreateProcessWithLogonW qui s'utilise comme CreateProcess sauf qu'il faut également spécifier le nom et le mot de passe de l'utilisateur qui désire créer le processus. Si elle est susceptible d'être appelée assez souvent dans le programme, alors il sera peut-être interessant de créer un handle vers un objet qui représente un utilisateur en utilisant la fonction LogonUser et d'appeler ensuite CreateProcessAsUser en fournissant ce handle chaque fois qu'on veut lancer un programme avec les droits de cet utilisateur. Il ne faut pas oublier de fermer le handle (CloseHandle) avant de quitter le programme.


Comment obtenir un handle vers un processus connaissant son nom ?
auteur : Melem
Cela n'est pas possible car plusieurs instances de l'application peuvent exister en mémoire au même moment. La seule information qui permet d'identifier un processus est le PID (Process ID), qui est un numéro unique attribué par Windows à chaque processus créé.


Comment obtenir un handle vers un processus connaissant son PID ?
auteur : Melem
A l'aide de la fonction OpenProcess. Toujours fermer le handle à l'aide de la fonction CloseHandle lorsqu'on en a plus besoin.


Comment ajuster les privilèges d'un processus ?
auteur : Melem
Pour faire certaines opérations, par exemple lire ou écrire dans la mémoire d'un autre processus, il faut avoir certains privilèges. La fonction AdjustTokenPrivileges premet d'ajuster les privilèges d'un processus. Voici un exemple (éteindre l'ordinateur) :
#include <windows.h>

void PowerOff()
{
    HANDLE hToken;                     /* Handle vers les privilèges du processus                     */
    TOKEN_PRIVILEGES token_privileges; /* Structure permettant de représenter un groupe de privilèges */
    LUID luid;                         /* Locally Unique ID (ID Local d'un privilège)                 */

    /* Il faut obtenir un handle vers les privilèges du processus qui nous intéresse.                 */

    OpenProcessToken( NULL,             /* Handle du processus                                        */
                      TOKEN_ALL_ACCESS, /* Ce que nous souhaitons faire avec le Token Handle          */
                      &hToken           /* Sortie                                                     */ );

    /* SE_SHUTDOWN_NAME ("SeShutdownPrivilege") est requis pour pouvoir éteindre l'ordinateur.        */
    /* Récupérons le LUID de ce privilège.                                                            */

    LookupPrivilegeValue( NULL,             /* Sur quelle machine ?                                   */
                          SE_SHUTDOWN_NAME, /* Nom du privilège dont le LUID nous intéresse           */
                          &luid             /* Sortie                                                 */ );

    /* Composons les nouveaux privilèges du processus.                                                */

    token_privileges.PrivilegeCount = 1;

    token_privileges.Privileges[0].Luid       = luid;
    token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    /* Appliquons.                                                                                    */

    AdjustTokenPrivileges( hToken,            /* Token Handle                                         */
                           FALSE,             /* Désactiver tous les privilèges ? (DAP)               */
                           &token_privileges, /* Nouvel état (ignoré si DAP vaut TRUE)                */
                           0,                 /* sizeof(old_state)                                    */
                           NULL,              /* &old_state                                           */
                           NULL               /* &retun_length                                        */ );

    /* C'est fait. Fermons le Token Handle.                                                           */

    CloseHandle(hToken);

    /* On peut maintenant éteindre l'ordinateur.                                                      */

    ExitWindowsEx(EWX_POWEROFF, 0);
}

Comment obtenir la liste de tous les processus en cours ?
auteur : Melem
Il existe actuellement deux APIs permettant de lister, entre autres, tous les processus en cours. La première est la Toolhelp API que les développeurs de Windows 9x/Me ont ajouté en "complément" à l'API Win32. La deuxième est la PSAPI (Process Status helper API) qui est la réponse (tardive) des développeurs de WINNT à la Toolhelp API. Cette API, implémentée par le fichier (redistribuable) psapi.dll, est incluse dans Windows 2000 et plus récents. En addition, la Toolhelp API a également été ajoutée à ces systèmes.

Voici un programme qui affiche la liste de tous les processus en cours en utilisant la Toolhelp API :
#include <stdio.h>
#include <windows.h>
#include <tlhelp32.h>

int main()
{
    HANDLE hSnapShot;
    PROCESSENTRY32 pe;

    /* Demander une vue de tous les processus en cours */
    hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    /* Afficher les résultats                          */
    if (Process32First(hSnapShot, &pe))
    {
        do
            printf("%-20s (pid = %4lu)\n", pe.szExeFile, pe.th32ProcessID);
        while (Process32Next(hSnapShot, &pe));
    }

    CloseHandle(hSnapShot);

    return 0;
}

Avec la PSAPI, on appelle EnumProcesses pour avoir les PIDs des différents processus en cours, esnuite OpenProcess sur chaque PID pour avoir un handle vers ce processus et enfin GetModuleBaseName ou GetModuleFileNameEx pour avoir le nom du processus (nom seulement avec la première et le chemin complet avec la seconde). Inclure psapi.h et ajouter psapi.lib dans les entrées du linkeur.


Comment obtenir la liste de tous les modules chargés par un processus ?
auteur : Melem
Toujours faisable avec la Toolhelp API ou la PSAPI. Le programme suivant utilise la Toolhelp API pour lister tous les modules chargés par lui-même.
#include <stdio.h>
#include <windows.h>
#include <tlhelp32.h>

int main()
{
    HANDLE hSnapShot;
    MODULEENTRY32 me;
    
    hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetCurrentProcessId());
    
    me.dwSize = sizeof(me); /* Il faut initialiser ce champ avant d'appeler Module32First. */
    
    if (Module32First(hSnapShot, &me))
    {
        do
            printf("%s\n", me.szModule);
        while (Module32Next(hSnapShot, &me));
    }
    
    CloseHandle(hSnapShot);
    
    return 0;
}
Remplacez me.szModule par me.szExePath pour avoir le chemin complet du module au lieu de son nom uniquement.

Avec la PSAPI, on appelle EnumProcessModules suivi de GetModuleBaseName ou GetModuleFileNameEx sur chaque module.


Que se passe-t-il si je ferme le handle d'un processus ou d'un thread avant que celui-ci s'est terminé ?
auteur : Melem
Rien de spécial. Fermer un handle vers un processus ou un thread ne le tue pas mais libère tout simplement le handle. Pour terminer un processus (respectivemet un thread), il faut appeler TerminateProcess (respectivement TerminateThread).


Comment obtenir l'ID du thread (ainsi que celui du processus ayant créé ce thread) ayant créé une fenêtre ?
auteur : Melem
A l'aide de la fonction GetWindowThreadProcessId.


Comment obtenir le chemin complet d'un processus ?
auteur : Melem
La fonction GetModuleFileName permet de connaître le chemin complet du processus courant. Pour obtenir le chemin complet d'un autre processus, on pourra utiliser la fonction GetModuleFileNameEx de la PSAPI. Il n'y a pas d'équivalent direct de cette fonction dans la Toolhelp API donc, avec cette API, on est obligé d'énumérer les modules chargés par le processus jusqu'à trouver l'exe lui-même.


Comment changer le répertoire courant ?
auteur : Melem
SetCurrentDirectory(<nouveau répertoire courant>).



Consultez les autres F.A.Q.


Valid XHTML 1.0 TransitionalValid CSS!

Les codes sources présentés sur cette page sont libres de droits, et vous pouvez les utiliser à votre convenance. Pour le reste, ce document constitue une oeuvre intellectuelle protégée par les droits d'auteurs. Ce document issu de http://www.developpez.com est soumis à deux licences, en fonction des contributeurs : - Les contributions de LFE sont soumises aux termes de la la licence GNU FDL traduite en français ici. Permission vous est donnée de distribuer, modifier des copies des contributions de LFE tant que cette note apparaît clairement : "Ce document issu de http://www.developpez.com est soumis à la licence GNU FDL traduite en français ici. Permission vous est donnée de distribuer, modifier des copies de cette page tant que cette note apparaît clairement". - Pour ce qui est des autres contributions : Copyright © 2002-2006 Developpez LLC : Tous droits réservés Developpez LLC. Aucune reproduction, ne peux en être faite sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.