2008-11-04 59 views

Respuesta

185

Esta es una manera de hacerlo con el nombre:

Process[] pname = Process.GetProcessesByName("notepad"); 
if (pname.Length == 0) 
    MessageBox.Show("nothing"); 
else 
    MessageBox.Show("run"); 

Puede recorrer todo el proceso para obtener el ID de la manipulación posterior:

Process[] processlist = Process.GetProcesses(); 
foreach(Process theprocess in processlist){ 
    Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id); 
} 
+0

Esto es exactamente lo que estaba buscando. Aunque esta es una publicación muy antigua, ¿podría explicarme cómo es válida C#? No lo dudo, veo que funciona, pero nunca he visto otra cosa sin {}. – MatthewD

+2

@MatthewD: las declaraciones C# 'if/else' que tienen solo una línea de longitud no necesitan tener llaves para indicar la instrucción de bloque. Esto también se aplica a las declaraciones 'foreach' y' for'. Todo se reduce al estilo de codificación. – Hallmanac

+0

Hice algunas investigaciones sobre esto también, encontré esa información, pero no vi la información 'for'. Años de desarrollo de C# .net y nunca he visto este estilo. Como dicen, "aprendes algo nuevo todos los días". Gracias por la publicación y la respuesta. – MatthewD

1

Process.GetProcesses() es el camino a seguir. Pero es posible que necesite usar uno o más criterios diferentes para encontrar su proceso, dependiendo de cómo se está ejecutando (es decir, como un servicio o una aplicación normal, tenga o no una barra de título).

+0

Si pone este método en un bucle, cuesta muchos ciclos de CPU. Recomiendo usar GetProcessByName() o GetProcessByID(). –

2

Depende de qué tan confiable desee que sea esta función. Si desea saber si la instancia de proceso particular que tiene todavía se está ejecutando y está disponible con un 100% de precisión, entonces no tiene suerte. La razón es que desde el objeto de proceso gestionado solo hay 2 formas de identificar el proceso.

El primero es el ID del proceso. Desafortunadamente, los identificadores de procesos no son únicos y pueden reciclarse. La búsqueda en la lista de procesos de un ID coincidente solo indicará que hay un proceso con el mismo ID ejecutándose, pero no es necesariamente su proceso.

El segundo elemento es la Manija de proceso. Aunque tiene el mismo problema que el Id y es más difícil trabajar con él.

Si busca una fiabilidad de nivel medio, basta con consultar la lista de procesos actual para obtener un proceso del mismo ID.

0

Tal vez (probablemente) estoy leyendo la pregunta erróneamente, pero ¿está buscando la propiedad HasExited que le dirá que el proceso representado por su objeto Proceso ha salido (normalmente o no).

Si el proceso al que hace referencia tiene una IU, puede usar la propiedad Respondiendo para determinar si la IU responde actualmente o no a la entrada del usuario.

También puede establecer EnableRaisingEvents y manejar el evento Exited (que se envía de forma asilómada) o llamar a WaitForExit() si desea bloquear.

11

solución síncrona:

void DisplayProcessStatus(Process process) 
{ 
    process.Refresh(); // Important 


    if(process.HasExited) 
    { 
     Console.WriteLine("Exited."); 
    } 
    else 
    { 
     Console.WriteLine("Running."); 
    } 
} 

solución asincrónica:

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."); 
} 
+5

Para la primera opción: ¿cómo puedo saber si el proceso se inició en primer lugar? – reshefm

22

Ésta es la forma más sencilla que encontré después de usar el reflector. creé un método de extensión para que:

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

El método Process.GetProcessById(processId) llama al método ProcessManager.IsProcessRunning(processId) y tiros ArgumentException en caso de que no exista el proceso. Por alguna razón, la clase ProcessManager es interna ...

+0

Esta fue una muy buena respuesta; sin embargo, no debería haber hecho a través del argumento excepción nula (Debido a que una excepción de referencia nula se habría lanzado de todos modos y no hizo nada con la excepción. Además, obtendrá una InvalidOperationException si no invocó el Inicio() método o invocó el método close(). Publiqué otra respuesta a la cuenta para estas dos situaciones. – Aelphaeis

0

Puede instanciar una instancia de proceso una vez para el proceso que desee y seguir rastreando el proceso utilizando ese objeto de proceso .NET (seguirá rastreando hasta que llame a Cerrar en ese objeto .NET explícitamente, incluso si el proceso que estaba rastreando ha muerto [esto es para poder darle tiempo de cierre del proceso, también conocido como ExitTime, etc.])

Citando http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx:

Cuando un salidas de proceso asociados (es decir, cuando se cierra por el sistema operación a través de una terminación normal o anormal), el sistema de información tiendas administrativa acerca de la procesa y vuelve al componente que había llamado WaitForExit. El componente Proceso puede entonces acceder a la información, que incluye ExitTime, utilizando el identificador al proceso salido.

Como el proceso asociado ha salido, la propiedad de control del componente ya no apunta a un recurso de proceso existente. En su lugar, , el identificador solo se puede usar para acceder a la información del sistema operativo sobre el recurso de proceso. El sistema conoce los identificadores a los procesos salidos que no han sido liberados por los componentes del Proceso, , por lo que mantiene la información de ExitTime and Handle en memoria hasta que el componente de proceso libera específicamente los recursos. Por este motivo, cada vez que llame a Iniciar para una instancia de proceso, llame a Close cuando el proceso asociado haya finalizado y ya no necesite ninguna información administrativa al respecto. Cerrar libera la memoria asignada al proceso salido.

0

He intentado la solución de Coincoin:
Antes de procesar algún archivo, lo copio como un archivo temporal y abrirlo.
Cuando he terminado, me cerrar la aplicación si aún está abierto y borrar el archivo temporal :
sólo tiene que utilizar una variable de proceso y comprobar que después:

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

Más tarde cerrar la aplicación:

... 
openApplication.Refresh(); 

// close application if it is still open  
if (!openApplication.HasExited()) { 
    openApplication.Kill(); 
} 

// delete temporary file 
System.IO.File.Delete(fileCache); 

funciona (hasta ahora)

+3

En 'openApplication.HasExited()', HasExited no es una función. La forma correcta sería 'openApplication.HasExited'. – caiosm1005

0
string process="notepad"; 
    if (Process.GetProcessesByName(process).Length == 0) 
    { 
    MessageBox.Show("Working"); 
    } 
    else 
    { 
    MessageBox.Show("Not Working"); 
    } 

al por lo que puede usar un temporizador para verificar el proceso cada vez

+1

Wouldn ¿No será al revés? Si la longitud == 0 significa que no funciona? –

+0

La respuesta es la misma que la de Patrick Desjardins: https://stackoverflow.com/a/262291/7713750 – Rekshino

7

reshefm tenía una respuesta bastante buena; sin embargo, no da cuenta de una situación en la que el proceso nunca comenzó.

Aquí hay una versión modificada de lo que publicó.

public static bool IsRunning(this Process process) 
    { 
     try {Process.GetProcessById(process.Id);} 
     catch (InvalidOperationException) { return false; } 
     catch (ArgumentException){return false;} 
     return true; 
    } 

Aparté su ArgumentNullException porque su realidad supone que debe ser una excepción de referencia nula y que sean desechados por el sistema de todos modos y también representaron la situación en la que el proceso nunca se inició, para empezar, o el cierre () método fue utilizado para cerrar el proceso.

+0

Personalmente, preferiría ver más una ArgumentNullException al revisar una excepción registrada que una NullReferenceException, ya que ArgumentNullException es mucho más explícita sobre lo que salió mal. – Sean

+1

@Sean normalmente lo haría estoy de acuerdo contigo, pero este es un método de extensión. Creo que es más apropiado lanzar una excepción de puntero nulo dada la sintaxis, simplemente se siente más consistente con los métodos de invocación de objetos nulos. – Aelphaeis

4

Esto debería ser una sola línea:

public static class ProcessHelpers { 
    public static bool IsRunning (string name) => Process.GetProcessesByName(name).Length > 0; 
} 
+2

No necesita el '? true: false' porque ya está devolviendo un booleano. – Melvin

+0

@melvin, gracias. Arreglado. – guneysus

0

pesar de API apoyado desde marcos .Net con respecto a la comprobación proceso existente por ID de proceso, esas funciones son muy lentos. Cuesta una gran cantidad de ciclos de CPU ejecutar Process.GetProcesses() o Process.GetProcessById/Name().

Un método mucho más rápido para verificar un proceso en ejecución por ID es utilizar la API nativa OpenProcess(). Si el identificador de devolución es 0, el proceso no existe. Si handle es diferente de 0, el proceso se está ejecutando. No hay garantía de que este método funcione al 100% en todo momento debido al permiso.

Cuestiones relacionadas