Domanda

Ho un'applicazione Winforms C# che di tanto in tanto deve avviare un exe esterno, ma non desidero avviare un altro processo se ne è già in esecuzione, ma piuttosto passare ad esso.

Quindi, come potrei farlo in C# nell'esempio seguente?

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(); 
}
È stato utile?

Soluzione

Questo dovrebbe bastarti.

Controlla i processi

//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;
}


Altri suggerimenti

Puoi anche usare LINQ,

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

Ho utilizzato la funzione AppActivate nel runtime VB per attivare un processo esistente.Dovrai importare la dll Microsoft.VisualBasic nel progetto 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);
        }
    }
}

Puoi semplicemente enumerare i processi utilizzando Process.GetProcesses metodo.

Ho scoperto che Mutex non funziona come nell'applicazione Console.Pertanto, l'utilizzo di WMI per interrogare i processi che possono essere visualizzati utilizzando la finestra Task Manager risolverà il tuo problema.

Usa qualcosa del genere:

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;
}

NOTA:Aggiungere il riferimento all'assembly "System.Management" per abilitare il tipo intellisense.

Penso che la risposta completa al tuo problema richieda la comprensione di cosa succede quando la tua applicazione determina che un'istanza di foo.exe è già in esecuzione, ovvero cosa fa '//TODO:Passare al processo foo.exe significa effettivamente?

In un progetto passato avevo bisogno di impedire l'esecuzione multipla di un processo, quindi ho aggiunto del codice nella sezione init di quel processo che crea un mutex denominato.Questo mutesto è stato creato e acquisito prima di continuare il resto del processo.Se il processo può creare il mutex e acquisirlo, allora è il primo in esecuzione.Se un altro processo controlla già il mutex, quello che fallisce non è il primo quindi esce immediatamente.

Stavo solo cercando di impedire l'esecuzione di una seconda istanza, a causa delle dipendenze su interfacce hardware specifiche.A seconda di ciò di cui hai bisogno con la riga "passa a", potresti aver bisogno di una soluzione più specifica come un ID o un handle di processo.

Inoltre, avevo accesso al codice sorgente del processo che stavo cercando di avviare.Se non puoi modificare il codice, aggiungere il mutex ovviamente non è un'opzione.

Due preoccupazioni da tenere a mente:

  1. Il tuo esempio ha comportato il posizionamento di una password su una riga di comando.Quella rappresentazione di ClearText di un segreto potrebbe essere una vulnerabilità di sicurezza.

  2. Quando elenchi i processi, chiediti quali processi vuoi davvero enumerarti.Tutti gli utenti o solo l'utente attuale?Cosa succede se l'utente corrente viene effettuato l'accesso due volte (due desktop)?

Mnebuerquo ha scritto:

Inoltre, avevo l'accesso al codice sorgente al processo che stavo cercando di iniziare.Se non è possibile modificare il codice, l'aggiunta di Mutex non è ovviamente un'opzione.

Non ho accesso al codice sorgente del processo che desidero eseguire.

Ho finito per utilizzare il processo MainWindowHandle per passare al processo una volta scoperto che è già in esecuzione:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 public static extern bool SetForegroundWindow(IntPtr hWnd);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top