visual - system.diagnostics c#
¿Cómo puedo saber si un proceso se está ejecutando? (12)
A pesar de la API admitida de los marcos .Net con respecto a la verificación del proceso existente por ID del proceso, esas funciones son muy lentas. 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 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.
Cuando obtengo una referencia a System.Diagnostics.Process
, ¿cómo puedo saber si un proceso se está ejecutando actualmente?
Depende de qué tan confiable quiera 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 proceso 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 confiabilidad de nivel medio, entonces es suficiente verificar la lista de procesos actual para un proceso de la misma ID.
Esta es la forma más sencilla que encontré después de usar el reflector. Creé un método de extensión para eso:
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 lanza ArgumentException
en caso de que el proceso no exista. Por algún motivo, la clase ProcessManager
es interna ...
Esta es una forma de hacerlo con el nombre:
Process[] pname = Process.GetProcessesByName("notepad");
if (pname.Length == 0)
MessageBox.Show("nothing");
else
MessageBox.Show("run");
Puede repetir todo el proceso para obtener la ID para una manipulación posterior:
Process[] processlist = Process.GetProcesses();
foreach(Process theprocess in processlist){
Console.WriteLine("Process: {0} ID: {1}", theprocess.ProcessName, theprocess.Id);
}
Esto debería ser un trazador de líneas:
public static class ProcessHelpers {
public static bool IsRunning (string name) => Process.GetProcessesByName(name).Length > 0;
}
Probé la solución de Coincoin:
Antes de procesar algún archivo, lo copio como un archivo temporal y lo abro.
Cuando termine, cierro la aplicación si todavía está abierta y elimino el archivo temporal:
Solo uso una variable de proceso y la compruebo a continuación:
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 cierro 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)
Puede instanciar una instancia de proceso una vez para el proceso que desea 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 proceso cercano, también conocido como ExitTime, etc.])
Citando http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx :
Cuando sale un proceso asociado (es decir, cuando el sistema de operación lo cierra a través de una terminación normal o anormal), el sistema almacena información administrativa sobre el proceso y regresa al componente que había llamado WaitForExit. El componente Proceso puede acceder a la información, que incluye ExitTime, utilizando el identificador para el proceso salido.
Debido a que el proceso asociado ha salido, la propiedad Handle del componente ya no apunta a un recurso de proceso existente. En cambio, el identificador solo se puede usar para acceder a la información del sistema operativo sobre el recurso del proceso. El sistema conoce los identificadores para los procesos salidos que no han sido liberados por los componentes del Proceso, por lo que mantiene la información de Tiempo de Exportación y Manejo en la memoria hasta que el componente Proceso libere específicamente los recursos. Por esta razón, cada vez que llame a Iniciar para una instancia de proceso, llame a Close cuando el proceso asociado haya finalizado y ya no necesite información administrativa al respecto. Cerrar libera la memoria asignada al proceso salido.
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.");
}
Tal vez (probablemente) estoy leyendo la pregunta incorrectamente, pero ¿está buscando la propiedad HasExited que le dirá que el proceso representado por su objeto Process ha salido (normalmente o no).
Si el proceso al que hace referencia tiene una UI, puede usar la propiedad Responding para determinar si la UI responde actualmente a la entrada del usuario o no.
También puede establecer EnableRaisingEvents y manejar el evento Exited (que se envía de forma asilógrada) o llamar a WaitForExit () si desea bloquear.
reshefm tuvo una respuesta bastante agradable; 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;
}
Eliminé su ArgumentNullException porque se supone que es una excepción de referencia nula y el sistema la lanza de todos modos y también explicaba la situación en la que el proceso nunca se inició o el método close () se usaba para cerrar el proceso.
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).
string process="notepad";
if (Process.GetProcessesByName(process).Length == 0)
{
MessageBox.Show("Working");
}
else
{
MessageBox.Show("Not Working");
}
también puede usar un temporizador para verificar el proceso cada vez