Question

J'ai une application Winforms C# qui doit démarrer un exe externe de temps en temps, mais je ne souhaite pas démarrer un autre processus s'il est déjà en cours d'exécution, mais plutôt y passer.

Alors, comment en C# pourrais-je faire cela dans l'exemple ci-dessous ?

using System.Diagnostics;

...

Process foo = new Process();

foo.StartInfo.FileName = @"C:\bar\foo.exe";
foo.StartInfo.Arguments = "Username Password";

bool isRunning = //TODO: Check to see if process foo.exe is already running


if (isRunning)
{
   //TODO: Switch to foo.exe process
}
else
{
   foo.Start(); 
}
Était-ce utile?

La solution

Cela devrait le faire pour toi.

Vérifier les processus

//Namespaces we need to use
using System.Diagnostics;

public bool IsProcessOpen(string name)
{
    //here we're going to get a list of all running processes on
    //the computer
    foreach (Process clsProcess in Process.GetProcesses()) {
        //now we're going to see if any of the running processes
        //match the currently running processes. Be sure to not
        //add the .exe to the name you provide, i.e: NOTEPAD,
        //not NOTEPAD.EXE or false is always returned even if
        //notepad is running.
        //Remember, if you have the process running more than once, 
        //say IE open 4 times the loop thr way it is now will close all 4,
        //if you want it to just close the first one it finds
        //then add a return; after the Kill
        if (clsProcess.ProcessName.Contains(name))
        {
            //if the process is found to be running then we
            //return a true
            return true;
        }
    }
    //otherwise we return a false
    return false;
}


Autres conseils

Vous pouvez également utiliser LINQ,

var processExists = Process.GetProcesses().Any(p => p.ProcessName.Contains("<your process name>"));

J'ai utilisé la fonction AppActivate dans le runtime VB pour activer un processus existant.Vous devrez importer la dll Microsoft.VisualBasic dans le projet C#.

using System;
using System.Diagnostics;
using Microsoft.VisualBasic;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            Process[] proc = Process.GetProcessesByName("notepad");
            Interaction.AppActivate(proc[0].MainWindowTitle);
        }
    }
}

Vous pouvez simplement énumérer les processus en utilisant Processus.GetProcesses méthode.

J'ai découvert que Mutex ne fonctionne pas comme dans l'application Console.Ainsi, l'utilisation de WMI pour interroger les processus visibles à l'aide de la fenêtre du Gestionnaire des tâches résoudra votre problème.

Utilisez quelque chose comme ceci :

static bool isStillRunning() {
   string processName = Process.GetCurrentProcess().MainModule.ModuleName;
   ManagementObjectSearcher mos = new ManagementObjectSearcher();
   mos.Query.QueryString = @"SELECT * FROM Win32_Process WHERE Name = '" + processName + @"'";
   if (mos.Get().Count > 1)
   {
        return true;
    }
    else
        return false;
}

NOTE:Ajoutez la référence d’assembly « System.Management » pour activer le type intellisense.

Je pense que la réponse complète à votre problème nécessite de comprendre ce qui se passe lorsque votre application détermine qu'une instance de foo.exe est déjà en cours d'exécution, c'est-à-dire que fait '//TODO :Passer au processus foo.exe signifie réellement ?

Dans un projet antérieur, j'avais besoin d'empêcher l'exécution multiple d'un processus, j'ai donc ajouté du code dans la section init de ce processus qui crée un mutex nommé.Ce mutext a été créé et acquis avant de poursuivre la suite du processus.Si le processus peut créer le mutex et l’acquérir, alors c’est le premier à s’exécuter.Si un autre processus contrôle déjà le mutex, alors celui qui échoue n'est pas le premier donc il se termine immédiatement.

J'essayais simplement d'empêcher l'exécution d'une deuxième instance, en raison de dépendances sur des interfaces matérielles spécifiques.En fonction de ce dont vous avez besoin avec cette ligne "passer à", vous aurez peut-être besoin d'une solution plus spécifique telle qu'un identifiant ou un handle de processus.

De plus, j'avais accès au code source du processus que j'essayais de démarrer.Si vous ne pouvez pas modifier le code, l'ajout du mutex n'est évidemment pas une option.

Deux préoccupations à garder à l’esprit :

  1. Votre exemple impliquait de placer un mot de passe sur une ligne de commande.Cette représentation en texte clair d'un secret pourrait être une vulnérabilité de sécurité.

  2. Lorsque vous énumérez les processus, demandez-vous quels processus vous souhaitez vraiment énumérer.Tous les utilisateurs, ou simplement l'utilisateur actuel?Et si l'utilisateur actuel est connecté deux fois (deux ordinateurs de bureau)?

Mnebuerquo a écrit :

De plus, j'avais un accès au code source au processus que j'essayais de commencer.Si vous ne pouvez pas modifier le code, l'ajout du mutex n'est évidemment pas une option.

Je n'ai pas accès au code source du processus que je souhaite exécuter.

J'ai fini par utiliser le processus MainWindowHandle pour passer au processus une fois que j'ai découvert qu'il était déjà en cours d'exécution :

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 public static extern bool SetForegroundWindow(IntPtr hWnd);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top