Pregunta

Tengo una aplicación C# winforms que necesita iniciar un exe externo de vez en cuando, pero no deseo iniciar otro proceso si ya hay uno ejecutándose, sino cambiar a él.

Entonces, ¿cómo haría esto en C# en el siguiente ejemplo?

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(); 
}
¿Fue útil?

Solución

Esto debería ser suficiente para ti.

Verificar procesos

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


Otros consejos

También puedes usar LINQ,

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

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

Simplemente puede enumerar procesos usando Proceso.GetProcesses método.

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

Utilice 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:Agregue la referencia de ensamblado "System.Management" para habilitar el tipo intellisense.

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

En un proyecto anterior necesitaba evitar la ejecución múltiple de un proceso, por lo que agregué un 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 con el resto del proceso.Si el proceso puede crear el mutex y adquirirlo, entonces es el primero en ejecutarse.Si otro proceso ya controla el mutex, entonces el que falla no es el primero, por lo que sale inmediatamente.

Solo estaba tratando de evitar que se ejecutara una segunda instancia debido a dependencias en 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 del proceso que estaba intentando iniciar.Si no puede modificar el código, agregar el mutex obviamente no es una opción.

Dos preocupaciones a tener en cuenta:

  1. Su ejemplo implicó colocar una contraseña en una línea de comando.Esa representación de ClearText de un secreto podría ser una vulnerabilidad de seguridad.

  2. Cuando enumere los procesos, pregúntese qué procesos realmente desea enumerar.¿Todos los usuarios o solo el usuario actual?¿Qué pasa si el usuario actual se registra dos veces (dos escritorios)?

Mnebuerquo escribió:

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

No tengo acceso al código fuente del proceso que quiero ejecutar.

Terminé usando el proceso MainWindowHandle para cambiar al proceso una vez que descubrí que ya se está ejecutando:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 public static extern bool SetForegroundWindow(IntPtr hWnd);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top