Réponses:
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);
}
if/else
qui ne font qu'une seule ligne n'ont pas besoin d'accolades pour indiquer l'instruction de bloc. Cela vaut aussi pour foreach
et for
déclarations. Cela se résume au style de codage.
for
informations. Des années de développement c # .net et je n'ai jamais vu ce style. Comme on dit, "vous apprenez quelque chose de nouveau chaque jour". Merci pour le message et la réponse ..
C'est le moyen le plus simple que j'ai trouvé après avoir utilisé un 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)
méthode appelle la ProcessManager.IsProcessRunning(processId)
méthode et lance ArgumentException
au cas où le processus n'existe pas. Pour une raison quelconque, la ProcessManager
classe 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 a eu une assez bonne réponse; cependant, il ne tient pas compte d'une situation dans laquelle le processus n'a jamais commencé.
Voici une version modifiée de ce qu'il a publié.
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 parce qu'il suppose en fait être une exception de référence nulle et qu'il est de toute façon levé par le système et j'ai également pris en compte la situation dans laquelle le processus n'a jamais commencé ou la méthode close () a été utilisée pour fermer le processus.
Cela dépend de la fiabilité de cette fonction. Si vous voulez savoir si l'instance de processus particulière 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 qu'à partir de l'objet de processus géré, il n'y a que 2 façons 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. La recherche d'un identifiant correspondant dans la liste des processus vous indiquera uniquement 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 le même problème que l'Id et il est plus difficile de travailler avec.
Si vous recherchez une fiabilité de niveau moyen, il suffit de vérifier la liste de processus actuelle pour un processus du même ID.
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 la façon dont il s'exécute (c'est-à-dire en tant que service ou application normale, qu'il ait ou non une barre de titre).
Peut-être (probablement) que je lis mal la question, mais recherchez-vous la propriété HasExited qui vous dira que le processus représenté par votre objet Process s'est terminé (normalement ou non).
Si le processus auquel vous faites 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 à l'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.
Vous pouvez instancier une instance de processus une fois pour le processus souhaité et continuer à suivre le processus à l'aide de cet objet Process .NET (il continuera à suivre jusqu'à ce que vous appeliez explicitement Close sur cet objet .NET, même si le processus qu'il suivait est mort [ceci afin de pouvoir vous donner l'heure de la 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 d'exploitation via un arrêt normal ou anormal), le système stocke les informations administratives sur le processus et retourne au composant qui avait appelé WaitForExit. Le composant Process peut ensuite accéder aux informations, qui incluent l'ExitTime, en utilisant le Handle vers le processus quitté.
Étant donné que le processus associé s'est arrêté, la propriété Handle du composant ne pointe plus vers une ressource de processus existante. Au lieu de cela, le handle peut être utilisé uniquement pour accéder aux informations du système d'exploitation sur la ressource de processus. Le système est conscient des descripteurs de processus sortis 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 à ce sujet. Close libère la mémoire allouée au processus terminé.
J'ai essayé la solution de Coincoin:
avant de traiter un fichier, je le copie en tant que fichier temporaire et l'ouvre.
Quand j'ai terminé, je ferme l'application si elle est toujours ouverte et
je supprime le fichier temporaire: j'utilise juste une variable Process et je 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 );
Cela fonctionne (jusqu'à présent)
openApplication.HasExited()
, HasExited n'est pas une fonction. La bonne façon serait openApplication.HasExited
.
Malgré l'API prise en charge par les frameworks .Net concernant la vérification des processus existants par ID de processus, ces fonctions sont très lentes. Il en coûte énormément de cycles CPU pour exécuter Process.GetProcesses () ou Process.GetProcessById / Name ().
Une méthode beaucoup plus rapide pour vérifier un processus en cours par ID consiste à utiliser l'API native OpenProcess () . Si le handle de retour est 0, le processus n'existe pas. Si le handle est différent de 0, le processus est en cours d'exécution. Il n'y a aucune garantie que cette méthode fonctionnera à 100% à tout moment grâce à l'autorisation.
Il existe de nombreux problèmes associés à cela, car d'autres semblent partiellement résoudre:
Que les propriétés que d'autres ont mentionnées soient internes ou non, vous pouvez toujours obtenir des informations de leur part par réflexion si l'autorisation le permet.
var x = obj.GetType().GetProperty("Name", BindingFlags.NonPublic | BindingFlags.Instance);
Vous pouvez épingler du code Win32 pour Snapshot ou vous pouvez utiliser WMI qui est plus lent.
HANDLE CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);
Une autre option serait OpenProcess / CloseProcess, mais vous rencontrerez toujours les mêmes problèmes avec les exceptions levées comme avant.
Pour WMI - OnNewEvent.Properties ["?"]:
string process = "notepad";
if (Process.GetProcessesByName(process).Length == 0)
{
MessageBox.Show("Working");
}
else
{
MessageBox.Show("Not Working");
}
vous pouvez également utiliser une minuterie pour vérifier le processus à chaque fois
length == 0
devrait s'afficher Not Working
), mais le travail est toujours terminé.