2008-09-09 34 views
24

Tengo la aplicación C# winforms que necesita iniciar un exe externo de vez en cuando, pero no deseo iniciar otro proceso si ya se está ejecutando, sino cambiarlo.¿Cómo puedo saber si un proceso ya se está ejecutando usando C#?

Entonces, ¿cómo en C# me gustaría que esto en el ejemplo de abajo?

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

Respuesta

29

Esto debería hacerlo por ti.

Check Processes

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

 
+0

¿No sería seguro usar Equals en lugar de contains? Tu comentario no refleja cómo se comportará.
Si el nombre de spesifc es "notepad" va a encontrar notepad.exe y cualquier otro proceso que tenga el bloc de notas en su nombre. – EKS

+0

La línea 'foreach (Proceso clsProcess en Process.GetProcesses) {' debería leer 'foreach (Proceso clsProceso en Process.GetProcesses() {' –

+0

@John M - ¡Buenos ojos! Reparado – DaveK

1

Creo que la respuesta completa a su problema requiere una comprensión de lo que sucede cuando la aplicación determina que ya se está ejecutando una instancia de foo.exe, es decir, ¿qué significa '// TODO: cambiar a foo.exe'?

6

He utilizado la función AppActivate en el tiempo de ejecución de VB para activar un proceso existente. Tendrá que importar Microsoft.VisualBasic dll en el proyecto 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); 
     } 
    } 
} 
21

Puede utilizar LINQ, así,

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

En un proyecto anterior que necesitaba para evitar la ejecución múltiple de un proceso, por lo que añade un poco de código en la sección de inicio de ese proceso que crea un mutex con nombre. Este mutext fue creado y adquirido antes de continuar el resto del proceso. Si el proceso puede crear el mutex y adquirirlo, entonces es el primero en ejecución. Si otro proceso ya controla el mutex, entonces el que falla no es el primero, por lo que sale inmediatamente.

Estaba tratando de evitar que se ejecute una segunda instancia, debido a las dependencias en las interfaces de hardware específicas. Dependiendo de lo que necesite con esa línea "cambiar a", es posible que necesite una solución más específica, como una identificación o identificador de proceso.

Además, tenía acceso al código fuente al proceso que estaba tratando de iniciar. Si no puede modificar el código, agregar el mutex obviamente no es una opción.

0

Mnebuerquo escribió:

Además, he tenido acceso al código fuente para el proceso yo estaba tratando de empezar. Si no puede modificar el código, agregar el mutex obviamente no es una opción.

no tengo acceso al código fuente para el proceso que desea ejecutar.

he terminado con el MainWindowHandle proccess para cambiar al proceso una vez que he encontrado que se está ejecutando alread:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
public static extern bool SetForegroundWindow(IntPtr hWnd); 
1

Dos preocupaciones a tener en cuenta:

  1. Su ejemplo involucrados colocando una contraseña en una línea de comando. Esa representación en texto claro de un secreto podría ser una vulnerabilidad de seguridad.

  2. Al enumerar procesos, pregunte que procesa realmente quiere enumerar. Todos los usuarios, o solo el usuario actual? ¿Qué sucede si el usuario actual está conectado dos veces (dos equipos de escritorio )?

2

Descubrí que Mutex no funciona como en la aplicación de consola. Entonces, al usar WMI para consultar los procesos que se pueden ver usando la ventana del Administrador de tareas, se solucionará su problema.

usar algo como esto:

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: Añadir referencia de ensamblado "System.Management" para activar el tipo de IntelliSense.

+0

Este enfoque permite la inspección de los argumentos de línea de comando (mo [ "Línea de comando"]); – crokusek

Cuestiones relacionadas