web-dev-qa-db-fra.com

Comment puis-je savoir si un processus est en cours d'exécution?

Lorsque je reçois une référence à un System.Diagnostics.Process, comment puis-je savoir si un processus est en cours d'exécution?

130
reshefm

C'est une façon de le faire avec le nom:

Process[] pname = Process.GetProcessesByName("notepad");
if (pname.Length == 0)
  MessageBox.Show("nothing");
else
  MessageBox.Show("run");

Vous pouvez boucler tous les processus pour obtenir l'ID pour une manipulation ultérieure:

Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist){
   Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}
216

C'est la façon la plus simple que j'ai trouvée après avoir utilisé réflecteur . J'ai créé une méthode d'extension pour cela:

public static class ProcessExtensions
{
    public static bool IsRunning(this Process process)
    {
        if (process == null) 
            throw new ArgumentNullException("process");

        try
        {
            Process.GetProcessById(process.Id);
        }
        catch (ArgumentException)
        {
            return false;
        }
        return true;
    }
}

La méthode Process.GetProcessById(processId) appelle la méthode ProcessManager.IsProcessRunning(processId) et lève ArgumentException au cas où le processus n'existe pas. Pour une raison quelconque, la classe ProcessManager est interne ...

24
reshefm

Solution synchrone:

void DisplayProcessStatus(Process process)
{
    process.Refresh();  // Important


    if(process.HasExited)
    {
        Console.WriteLine("Exited.");
    }
    else
    {
        Console.WriteLine("Running.");
    } 
}

Solution asynchrone:

void RegisterProcessExit(Process process)
{
    // NOTE there will be a race condition with the caller here
    //   how to fix it is left as an exercise
    process.Exited += process_Exited;
}

static void process_Exited(object sender, EventArgs e)
{
   Console.WriteLine("Process has exited.");
}
14
Coincoin

reshefm a eu une jolie réponse agréable; cependant, cela ne tient pas compte d'une situation dans laquelle le processus n'a jamais été commencé.

Voici une version modifiée de ce qu'il a posté.

    public static bool IsRunning(this Process process)
    {
        try  {Process.GetProcessById(process.Id);}
        catch (InvalidOperationException) { return false; }
        catch (ArgumentException){return false;}
        return true;
    }

J'ai supprimé son exception ArgumentNullException car elle est supposée être une exception de référence nulle. Le système l’a renvoyée de toute façon et j’ai également expliqué la situation dans laquelle le processus n’a jamais été commencé, ou la méthode close () a été utilisée pour fermer le fichier. processus.

9
Aelphaeis

Cela devrait être un one-liner:

public static class ProcessHelpers {
    public static bool IsRunning (string name) => Process.GetProcessesByName(name).Length > 0;
}
5
guneysus

Cela dépend de la fiabilité de cette fonction. Si vous voulez savoir si votre instance de processus particulière est toujours en cours d'exécution et disponible avec une précision de 100%, vous n'avez pas de chance. La raison en est que, à partir de l'objet de processus géré, il n'y a que 2 façons d'identifier le processus.

Le premier est l'identifiant du processus. Malheureusement, les identifiants de processus ne sont pas uniques et peuvent être recyclés. La recherche d'un identifiant correspondant dans la liste de processus vous indiquera seulement qu'un processus avec le même identifiant est en cours d'exécution, mais ce n'est pas nécessairement votre processus.

Le deuxième élément est le descripteur de processus. Il a cependant le même problème que l’Id et il est plus délicat de travailler avec.

Si vous recherchez une fiabilité de niveau moyen, il suffit de vérifier la liste de processus en cours pour un processus du même identifiant. 

3
JaredPar

Process.GetProcesses() est le chemin à parcourir. Mais vous devrez peut-être utiliser un ou plusieurs critères différents pour trouver votre processus, en fonction de son exécution (c'est-à-dire en tant que service ou application normale, qu'il ait ou non une barre de titre).

1
Jeff Kotula

Malgré les API prises en charge par les infrastructures .Net pour la vérification des processus existants par ID de processus, ces fonctions sont très lentes. L'exécution de Process.GetProcesses () ou de Process.GetProcessById/Name () coûte énormément de cycles de processeur.

Une méthode beaucoup plus rapide pour vérifier un processus en cours par ID consiste à utiliser une API native OpenProcess () . Si la valeur renvoyée est 0, le processus n'existe pas. Si handle est différent de 0, le processus est en cours d'exécution. Il n'y a aucune garantie que cette méthode fonctionne à 100% à tout moment en raison d'une permission.

0
Hao Nguyen

Peut-être (probablement) que je lis la question à tort, mais cherchez-vous la propriété HasExited qui vous indiquera que le processus représenté par votre objet Process a abouti (normalement ou non).

Si le processus pour lequel vous avez une référence possède une interface utilisateur, vous pouvez utiliser la propriété Responding pour déterminer si l'interface utilisateur répond actuellement à une entrée utilisateur ou non.

Vous pouvez également définir EnableRaisingEvents et gérer l'événement Exited (qui est envoyé de manière asynchrone) ou appeler WaitForExit () si vous souhaitez bloquer.

0
Ross

J'ai essayé la solution de Coincoin:
Avant de traiter un fichier, je le copie en tant que fichier temporaire et l’ouvre.
Lorsque j'ai terminé, je ferme l'application si elle est toujours ouverte et supprime Le fichier temporaire:
Je viens d'utiliser une variable de processus et de la vérifier après:

private Process openApplication;  
private void btnOpenFile_Click(object sender, EventArgs e) {  
    ...
    // copy current file to fileCache  
    ...  
    // open fileCache with proper application
    openApplication = System.Diagnostics.Process.Start( fileCache );  
}

Plus tard je ferme l'application: 

 ...   
openApplication.Refresh(); 

// close application if it is still open       
if ( !openApplication.HasExited() ) {
    openApplication.Kill();  
}

// delete temporary file  
System.IO.File.Delete( fileCache );

Cela fonctionne (jusqu'à présent)

0
Jack Griffin
    string process="notepad";
    if (Process.GetProcessesByName(process).Length == 0)
    {
    MessageBox.Show("Working");
    }
    else
    {
    MessageBox.Show("Not Working");
    }

aussi vous pouvez utiliser une minuterie pour vérifier le processus à chaque fois

0
berkay

Vous pouvez instancier une instance de processus une fois pour le processus souhaité et continuer à suivre le processus à l'aide de cet objet de processus .NET (il continuera à suivre jusqu'à ce que vous appeliez Close sur cet objet .NET de manière explicite, même si le processus qu'il suivait est mort [c'est pour pouvoir vous donner l'heure de fermeture du processus, aka ExitTime etc.])

Citant http://msdn.Microsoft.com/en-us/library/fb4aw7b8.aspx :

Lorsqu'un processus associé se termine (c'est-à-dire lorsqu'il est arrêté par le système en fonctionnement via une terminaison normale ou anormale), le système stocke les informations administratives sur le processus et retourne au fichier composant qui avait appelé WaitForExit. Le composant Process peut alors accéder aux informations, y compris ExitTime, à l’aide de Gérer le processus abandonné. 

Étant donné que le processus associé a abouti, la propriété Handle du fichier le composant ne pointe plus vers une ressource de processus existante. Au lieu, la poignée ne peut être utilisée que pour accéder au fichier .__ du système d’exploitation. informations sur la ressource de processus. Le système connaît les descripteurs aux processus sortis qui n'ont pas été publiés par les composants Process, il garde donc les informations ExitTime et Handle en mémoire jusqu'au Le composant de processus libère spécifiquement les ressources. Pour cette raison, chaque fois que vous appelez Démarrer pour une instance de processus, appelez Fermer lorsque le processus associé est terminé et vous n’avez plus besoin de informations administratives à ce sujet. Close libère la mémoire allouée au processus abandonné.

0
George Birbilis

Cela pose de nombreux problèmes, d'autres semblant en partie résoudre partiellement:

  • Il n'est pas garanti que les membres d'instance soient thread-safe Cela signifie que certaines situations peuvent survenir avec la durée de vie de l'instantané lors de la tentative d'évaluation des propriétés de l'objet.
  • Le descripteur de processus lancera Win32Exception pour ACCESS DENIED où les autorisations pour évaluer ceci et d'autres propriétés similaires ne sont pas autorisées.
  • Pour le statut ISN'T RUNNING, une exception ArgumentException sera également déclenchée lors de la tentative d'évaluation de certaines de ses propriétés.

Que les propriétés mentionnées par d'autres personnes soient internes ou non, vous pouvez toujours obtenir des informations auprès d'eux par réflexion si l'autorisation vous le permet.

var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);

Vous pouvez identifier le code Win32 pour Snapshot ou vous pouvez utiliser WMI qui est plus lent.

HANDLE CreateToolhelp32Snapshot(
  DWORD dwFlags,
  DWORD th32ProcessID
);

Une autre option serait de OpenProcess / CloseProcess, mais vous rencontrerez toujours les mêmes problèmes, les exceptions étant levées de la même manière qu'auparavant.

Pour WMI - OnNewEvent.Properties ["?"]:

  • "ParentProcessID"
  • "ProcessID"
  • "Nom du processus"
  • "SECURITY_DESCRIPTOR"
  • "ID de session"
  • "Sid"
  • "TIME_CREATED"
0
Latency