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?
C’est un moyen 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); }
C’est la manière la plus simple que j’ai trouvée après avoir utilisé le 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 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 …
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."); }
reshefm avait une très jolie réponse; Cependant, cela ne tient pas compte d’une situation dans laquelle le processus n’a jamais été démarré.
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 ArgumentNullException car il est en fait supposé être une exception de référence null et il est de toute façon jeté par le système et j’ai également pris en compte la situation dans laquelle le processus n’a jamais été démarré ou la méthode close () a été utilisée. processus.
Cela devrait être un one-liner:
public static class ProcessHelpers { public static bool IsRunning (ssortingng name) => Process.GetProcessesByName(name).Length > 0; }
Cela dépend de la fiabilité de cette fonction. Si vous voulez savoir si l’instance de processus que vous avez 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, depuis l’object de processus géré, il n’y a que deux manières d’identifier le processus.
Le premier est l’ID de processus. Malheureusement, les identifiants de processus ne sont pas uniques et peuvent être recyclés. Rechercher un identifiant correspondant dans la liste des processus ne vous indiquera qu’un processus avec le même identifiant, mais ce n’est pas nécessairement votre processus.
Le deuxième élément est la poignée de processus. Le problème est identique à celui de l’ID et il est plus difficile de travailler avec.
Si vous recherchez une fiabilité de niveau moyen, la vérification de la liste de processus en cours pour un processus du même ID est suffisante.
Process.GetProcesses()
est la voie à suivre. Mais vous devrez peut-être utiliser un ou plusieurs critères différents pour trouver votre processus, en fonction de son fonctionnement (par exemple, en tant que service ou application normale, avec ou sans barre de titre).
Peut-être (probablement) que je lis mal la question, mais cherchez-vous la propriété HasExited qui vous indiquera que le processus représenté par votre object Process s’est terminé (normalement ou non).
Si le processus dont vous avez une référence à une interface utilisateur, vous pouvez utiliser la propriété Responding pour déterminer si l’interface utilisateur répond actuellement aux entrées de l’utilisateur ou non.
Vous pouvez également définir EnableRaisingEvents et gérer l’événement Exited (envoyé de manière asynchrone) ou appeler WaitForExit () si vous souhaitez bloquer.
Vous pouvez instancier une instance de processus une fois pour le processus souhaité et continuer à suivre le processus à l’aide de cet object .NET Process (il continuera à suivre jusqu’à ce que vous appeliez explicitement cet object .NET, même si le processus qu’il suivait est mort) [c’est pour pouvoir vous donner l’heure de fermeture du processus, alias 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 d’exploitation via une terminaison normale ou anormale), le système stocke les informations administratives relatives au processus et renvoie au composant qui avait appelé WaitForExit. Le composant Process peut ensuite accéder aux informations, y compris ExitTime, en utilisant le handle du processus existant.
Étant donné que le processus associé est terminé, la propriété Handle du composant ne pointe plus vers une ressource de processus existante. Au lieu de cela, le handle ne peut être utilisé que pour accéder aux informations du système d’exploitation sur la ressource de processus. Le système a connaissance des descripteurs des processus sortants qui n’ont pas été libérés par les composants Process. Il conserve donc les informations ExitTime et Handle en mémoire jusqu’à ce que le composant Process libère spécifiquement les ressources. Pour cette raison, chaque fois que vous appelez Start pour une instance de processus, appelez Close lorsque le processus associé est terminé et que vous n’avez plus besoin d’informations administratives à son sujet. Close libère la mémoire allouée au processus sorti.
J’ai essayé la solution de Coincoin:
Avant de traiter un fichier, je le copie en tant que fichier temporaire et l’ouvre.
Une fois terminé, je ferme l’application si elle est toujours ouverte et supprime le fichier temporaire:
J’utilise juste une variable de processus et la vérifie ensuite:
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 );
Ça marche (jusqu’ici)
ssortingng process="notepad"; if (Process.GetProcessesByName(process).Length == 0) { MessageBox.Show("Working"); } else { MessageBox.Show("Not Working"); }
vous pouvez également utiliser une timer pour vérifier le processus à chaque fois
Malgré les API sockets en charge par les frameworks .Net concernant la vérification des processus existants par ID de processus, ces fonctions sont très lentes. L’exécution de Process.GetProcesses () ou Process.GetProcessById / Name () coûte énormément de temps processeur.
Une méthode beaucoup plus rapide pour vérifier un processus en cours d’exécution par ID consiste à utiliser l’API OpenProcess () native . Si le handle de retour 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 de la permission.