2017-09-05 4 views
0

몇 가지 프로세스를 시작하는 응용 프로그램이 있습니다. 이 응용 프로그램의 목적은 실행 된 후 실행 중인지 여부를 모니터링하고 실행 중이 아니면 응답하지 않거나 다시 실행되지 않는 경우 프로세스를 종료하는 것입니다. 응용 프로그램이 처음에 실행하는 것으로 알고있는 각 프로세스를 실행하고 ObtenerProceso 함수로 실행 중인지 확인 (프로세스가 시작될 때 각 프로세스의 PID가 있지만 프로세스가 작동하지 않고 다른 프로세스가 동일한 프로세스를 수행하는지 확인하지 않음) PID).다른 응용 프로그램에서 실행 한 프로세스가 실행 중인지 확인하는 방법은 무엇입니까?

public static Process ObtenerProceso(int pid, string ubicacion, string argumentos = "", string dominio = "", string usuario = "") 
{ 
    Process proceso = null; 
    Process procesoAux = null; 

    if (Process.GetProcesses().Any(x => x.Id == pid)) 
    { 
     procesoAux = Process.GetProcessById(pid); 
     if (procesoAux.MainModule.FileName.ToUpper() == ubicacion.ToUpper()) 
     { 
      ManagementObjectSearcher mos = new ManagementObjectSearcher($"select * from Win32_Process where ProcessId = {procesoAux.Id}"); 
      foreach (ManagementObject mo in mos.Get()) 
       if (mo["CommandLine"] != null && mo["CommandLine"].ToString().ToUpper().Replace($"\"{ubicacion.ToUpper()}\"", string.Empty).Trim() == argumentos.ToUpper().Trim()) 
       { 
        if (dominio.Trim() != string.Empty && usuario.Trim() != string.Empty) 
        { 
         string[] argList = new string[] { string.Empty, string.Empty }; 
         int respuesta = Convert.ToInt32(mo.InvokeMethod("GetOwner", argList)); 
         if (respuesta == 0 && $"{argList[1]}\\{argList[0]}".ToUpper() == $"{dominio}\\{usuario}".ToUpper()) 
          proceso = procesoAux; 
        } 
        else 
         proceso = procesoAux; 
       } 
     } 

    } 

    return proceso; 
} 

기능은 프로세스를 찾을 수없는 경우 null를 반환합니다.

이 방법은 저에게 효과적입니다. 문제는 모니터해야하는 프로세스의 수에 약간의 시간이 걸리는 것입니다. 가장 많은 시간을 소비 한 것은 select 문에 있었으며 프로세스를 실행 한 사용자 및 실행 파일로 보낸 명령 줄에 대한 자세한 정보를 가져옵니다.

더 효과적인 방법이 있습니까?

단일 실행에서 추가 설명이

응용 프로그램이 너무 이름으로 프로세스를 캡처, (그러나 다른 초기화 인수) 여러 인스턴스를 시작해야한다는 명령 라인으로 그들을 구별하는 경우에는 사용하지 않는 것이 좋습니다있는 프로세스가 실행되었습니다. 또한 프로세스가 두 가지 기준으로 응답하는지 확인합니다. 먼저 Process.Responding 속성을 사용하고 두 번째 모든 프로세스는 언제든지 SQLite 데이터베이스에서 업데이트를 시작하여 내 응용 프로그램이 프로세스의 마지막 보고서를 알고 쿼리 할 수 ​​있는지 확인합니다 "잠겨 있지 않은". 실행하고 모니터링 할 프로세스를 나타내는 Aplicacion 클래스를 알려 드리겠습니다.

using System; 
using System.Data; 
using System.Diagnostics; 
using System.Globalization; 
using System.IO; 
using System.Security; 

namespace Yggdrasil 
{ 
    /// <summary> 
    /// Represents an Application to be monitored. 
    /// </summary> 
    internal class Aplicacion 
    { 
     #region Definition of private variables. 
     private int id; 
     private int idMaquina; 
     private int pid = -999999999; 
     private string nombre; 
     private string descripcion; 
     private string ubicacion; 
     private string argumentos; 
     private string dominio; 
     private string usuario; 
     private SecureString clave; 
     private bool activa; 
     private DateTime fechaCreacion; 
     #endregion 

     #region Properties. 
     /// <summary> 
     /// Gets the Application ID. This property can not be set. 
     /// </summary> 
     public int Id 
     { 
      get 
      { 
       return id; 
      } 
     } 

     /// <summary> 
     /// Gets the identification of the process of the Application. This property can not be set. 
     /// </summary> 
     public int PID 
     { 
      get 
      { 
       return pid; 
      } 
     } 

     /// <summary> 
     /// Gets the identification of the Machine where the Application is executed. This property can not be set. 
     /// </summary> 
     public int IdMaquina 
     { 
      get 
      { 
       return idMaquina; 
      } 
     } 

     /// <summary> 
     /// Gets the name of the Application. This property can not be set. 
     /// </summary> 
     public string Nombre 
     { 
      get 
      { 
       return nombre; 
      } 
     } 

     /// <summary> 
     /// Gets the description of the Application. This property can not be set. 
     /// </summary> 
     public string Descripcion 
     { 
      get 
      { 
       return descripcion; 
      } 
     } 

     /// <summary> 
     /// Gets the location of the Application executable. This property can not be set. 
     /// </summary> 
     public string Ubicacion 
     { 
      get 
      { 
       return ubicacion; 
      } 
     } 

     /// <summary> 
     /// Gets the start arguments for the application. This property can not be set. 
     /// </summary> 
     public string Argumentos 
     { 
      get 
      { 
       return argumentos; 
      } 
     } 

     /// <summary> 
     /// Determines whether the Application is active or inactive. This property can not be set. 
     /// </summary> 
     public bool Activa 
     { 
      get 
      { 
       return activa; 
      } 
     } 

     /// <summary> 
     /// Gets the user with which the application is executed. This property can not be set. 
     /// </summary> 
     public string Usuario 
     { 
      get 
      { 
       return usuario; 
      } 
     } 

     /// <summary> 
     /// Gets the domain in which the application runs. This property can not be set. 
     /// </summary> 
     public string Dominio 
     { 
      get 
      { 
       return dominio; 
      } 
     } 

     /// <summary> 
     /// Gets the password of the user with whom the application is running. This property can not be set. 
     /// </summary> 
     public SecureString Clave 
     { 
      get 
      { 
       return clave; 
      } 
     } 

     /// <summary> 
     /// Gets the last date the application responded. This property can not be set. 
     /// </summary> 
     public DateTime FechaResponde 
     { 
      get 
      { 
       return ObtenerUltimoRespondeProceso(); 
      } 
     } 

     /// <summary> 
     /// Gets the last date the application reported activity. This property can not be set. 
     /// </summary> 
     public DateTime FechaReporte 
     { 
      get 
      { 
       return ObtenerUltimoReporteProceso(); 
      } 
     } 

     /// <summary> 
     /// Gets the date of creation of the application record. This property can not be set. 
     /// </summary> 
     public DateTime FechaCreacion 
     { 
      get 
      { 
       return fechaCreacion; 
      } 
     } 
     #endregion 

     #region implementación de constructores. 
     /// <summary> 
     /// Initializes an object from the Application class. 
     /// </summary> 
     /// <param name="id">Identification of the application.</param> 
     public Aplicacion(int id) 
     { 
      Inicializar(id); 
     } 

     /// <summary> 
     /// Initializes an object from the Application class. 
     /// </summary> 
     /// <param name="id">Identification of the application.</param> 
     /// <param name="idMaquina">Identification of the machine where the application is running.</param> 
     /// <param name="nombre">Name of the application.</param> 
     /// <param name="descripcion">Description of the application.</param> 
     /// <param name="ubicacion">Location of the application executable.</param> 
     /// <param name="argumentos">Arguments with which the application is executed.</param> 
     /// <param name="dominio">User domain of the application.</param> 
     /// <param name="usuario">User with which the application is executed.</param> 
     /// <param name="clave">Password of the user with which the application is executed.</param> 
     /// <param name="activa">Indicates whether the application is active or inactive.</param> 
     /// <param name="fechaCreacion">Creation date of the application record.</param> 
     public Aplicacion(int id, int idMaquina, string nombre, string descripcion, string ubicacion, string argumentos, string dominio, string usuario, string clave, int pid, bool activa, DateTime fechaCreacion) 
     { 
      this.id = id; 
      this.idMaquina = idMaquina; 
      this.nombre = nombre; 
      this.descripcion = descripcion; 
      this.ubicacion = ubicacion; 
      this.argumentos = argumentos; 
      this.activa = activa; 
      this.fechaCreacion = fechaCreacion; 
      this.dominio = dominio; 
      this.usuario = usuario.ToUpper(); 
      this.clave = Utilidades.String2SecureString(clave); 
      this.pid = pid; 
     } 
     #endregion 

     #region Implementación de métodos privados. 
     /// <summary> 
     /// Initializes an object of the Application class knowing its identification. 
     /// </summary> 
     /// <param name="id">Identification of the Application.</param> 
     private void Inicializar(int id) 
     { 
      try 
      { 
       using (ControladorSQLite controladorBD = new ControladorSQLite(Controlador.UbicacionBDLocal)) 
       { 
        DataTable dtAplicacion = controladorBD.EjecutarLector($"SELECT * FROM aplicacion WHERE id_aplicacion = {id}"); 
        foreach (DataRow drAplicacion in dtAplicacion.Rows) 
        { 
         this.id = id; 
         idMaquina = Convert.ToInt32(drAplicacion["id_maquina"]); 
         nombre = drAplicacion["nombre_aplicacion"].ToString(); 
         descripcion = drAplicacion["descripcion"].ToString(); 
         ubicacion = drAplicacion["ubicacion"].ToString(); 
         argumentos = drAplicacion["argumentos"].ToString(); 
         dominio = drAplicacion["dominio"].ToString(); 
         usuario = drAplicacion["usuario"].ToString().ToUpper(); 
         clave = Utilidades.String2SecureString(drAplicacion["clave"].ToString()); 
         if (drAplicacion["activa"].ToString() == "S") 
          activa = true; 
         else 
          activa = false; 
         pid = Convert.ToInt32(drAplicacion["pid"]); 
         fechaCreacion = (DateTime)drAplicacion["fecha_creacion"]; 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       throw new Exception($"Error al inicializar un objeto Aplicacion. {ex.Message}"); 
      } 
     } 

     /// <summary> 
     /// Updates the PID of the Application. 
     /// </summary> 
     /// <param name="pid">New process identification for the Application.</param> 
     private void ActualizarPID(int pid) 
     { 
      try 
      { 
       using (ControladorSQLite controladorBD = new ControladorSQLite(Controlador.UbicacionBDLocal)) 
       { 
        controladorBD.Ejecutar($"UPDATE aplicacion SET pid = {pid} WHERE id_aplicacion = {id}"); 
        this.pid = pid; 
       } 
      } 
      catch (Exception ex) 
      { 
       throw new Exception($"Error al intentar actualizar el PID. {ex.Message}"); 
      } 
     } 

     /// <summary> 
     /// Gets the date of the last report of the process. 
     /// </summary> 
     /// <returns></returns> 
     private DateTime ObtenerUltimoReporteProceso() 
     { 
      DateTime fecha = DateTime.Now; 
      Process proceso = ObtenerProcesoActual(); 

      try 
      { 
       using (ControladorSQLite controladorBD = new ControladorSQLite(Controlador.UbicacionBDLocal)) 
       { 
        int cantidad = Convert.ToInt32(controladorBD.EjecutarLector($"SELECT COUNT(*) AS cantidad FROM reporte_proceso WHERE id_proceso = {proceso.Id} AND UPPER(ubicacion) = '{ubicacion.ToUpper()}'").Rows[0]["cantidad"]); 
        if (cantidad > 0) 
        { 
         if (cantidad > 1000) 
          controladorBD.Ejecutar($"DELETE FROM reporte_proceso WHERE id_proceso = {proceso.Id} AND UPPER(ubicacion) = '{ubicacion.ToUpper()}'"); 

         fecha = DateTime.ParseExact(controladorBD.EjecutarLector($"SELECT STRFTIME('%d-%m-%Y %H:%M:%S', DATETIME(x.fecha)) AS fecha FROM (SELECT MAX(fecha_creacion) AS fecha FROM reporte_proceso WHERE id_proceso = {proceso.Id} AND UPPER(ubicacion) = '{ubicacion.ToUpper()}') x").Rows[0]["fecha"].ToString(), "dd-MM-yyyy HH:mm:ss", CultureInfo.InvariantCulture); 
        } 
       } 
      } 
      catch (Exception ex) 
      { 
       throw new Exception($"Error al intentar obtener la fecha del último reporte de una aplicación. {ex.Message}"); 
      } 

      return fecha; 
     } 

     /// <summary> 
     /// Gets the date of the last time the application replied. 
     /// </summary> 
     /// <returns></returns> 
     private DateTime ObtenerUltimoRespondeProceso() 
     { 
      DateTime fecha = DateTime.Now; 

      try 
      { 
       using (ControladorSQLite controladorBD = new ControladorSQLite(Controlador.UbicacionBDLocal)) 
       { 
        object obj_fecha = controladorBD.EjecutarLector($"SELECT STRFTIME('%d-%m-%Y %H:%M:%S', DATETIME(fecha_responde)) AS fecha FROM aplicacion WHERE id_aplicacion = {id}").Rows[0]["fecha"]; 
        if (obj_fecha != null) 
         fecha = DateTime.ParseExact(Convert.ToString(obj_fecha), "dd-MM-yyyy HH:mm:ss", CultureInfo.InvariantCulture); 
       } 
      } 
      catch (Exception ex) 
      { 
       throw new Exception($"Error al intentar obtener la última fecha de respuesta de una aplicación {ex.Message}"); 
      } 

      return fecha; 
     } 

     /// <summary> 
     /// Gets the current application process. 
     /// </summary> 
     /// <returns></returns> 
     private Process ObtenerProcesoActual() 
     { 
      return Utilidades.ObtenerProceso(pid, ubicacion, argumentos, dominio, usuario); 
     } 
     #endregion 

     #region Implementation of public methods 
     /// <summary> 
     /// Inactiva el proceso. 
     /// </summary> 
     public void Inactivar() 
     { 
      try 
      { 
       using (ControladorSQLite controladorBD = new ControladorSQLite(Controlador.UbicacionBDLocal)) 
        controladorBD.Ejecutar($"UPDATE aplicacion SET activa = 'N' WHERE id_aplicacion = {id} AND activa = 'S'"); 
      } 
      catch (Exception ex) 
      { 
       throw new Exception($"Error al intentar inactivar una aplicación. {ex.Message}"); 
      } 
     } 

     /// <summary> 
     /// Activate the process. 
     /// </summary> 
     public void Activar() 
     { 
      try 
      { 
       using (ControladorSQLite controladorBD = new ControladorSQLite(Controlador.UbicacionBDLocal)) 
        controladorBD.Ejecutar($"UPDATE aplicacion SET activa = 'S' WHERE id_aplicacion = {id} AND activa = 'N'"); 
      } 
      catch (Exception ex) 
      { 
       throw new Exception($"Error al intentar activar una aplicación. {ex.Message}"); 
      } 
     } 

     /// <summary> 
     /// Updates the last date the application responded. 
     /// </summary> 
     public void ActualizarRespuesta() 
     { 
      try 
      { 
       using (ControladorSQLite controladorBD = new ControladorSQLite(Controlador.UbicacionBDLocal)) 
        controladorBD.Ejecutar($"UPDATE aplicacion SET fecha_responde = CURRENT_TIMESTAMP WHERE id_aplicacion = {id}"); 
      } 
      catch (Exception ex) 
      { 
       throw new Exception($"Error al intentar actualizar la fecha de respuesta de una aplicación. {ex.Message}"); 
      } 
     } 

     /// <summary> 
     /// Deletes the configuration application. 
     /// </summary> 
     public void Eliminar() 
     { 
      try 
      { 
       using (ControladorSQLite controladorBD = new ControladorSQLite(Controlador.UbicacionBDLocal)) 
        controladorBD.Ejecutar($"DELETE FROM aplicacion WHERE id_aplicacion = {id}"); 
      } 
      catch (Exception ex) 
      { 
       throw new Exception($"Error al intentar eliminar una aplicaión. {ex.Message}"); 
      } 
     } 

     /// <summary> 
     /// Checks if the application is running. 
     /// </summary> 
     /// <returns></returns> 
     public bool EnEjecucion() 
     { 
      return ObtenerProcesoActual() != null; 
     } 

     /// <summary> 
     /// Determines whether the application is responding. 
     /// </summary> 
     /// <returns></returns> 
     public bool EstaRespondiendo() 
     { 
      return ObtenerProcesoActual().Responding; 
     } 

     /// <summary> 
     /// Run the application. 
     /// </summary> 
     public void Ejecutar() 
     { 
      Process proceso = new Process() 
      { 
       StartInfo = new ProcessStartInfo() 
       { 
        FileName = ubicacion, 
        ErrorDialog = true, 
        UseShellExecute = false, 
        RedirectStandardOutput = true, 
        RedirectStandardError = true, 
        WorkingDirectory = Path.GetDirectoryName(ubicacion), 
        Arguments = argumentos, 
        Domain = dominio, 
        UserName = usuario, 
        Password = clave 
       } 
      }; 

      proceso.Start(); 
      ActualizarPID(proceso.Id); 
     } 

     /// <summary> 
     /// Kills the current application process. 
     /// </summary> 
     public void Matar() 
     { 
      ObtenerProcesoActual().Kill(); 
     } 
     #endregion 
    } 
} 
+0

프로세스 핸들은 대기 가능한 객체입니다. (예 : https://msdn.microsoft.com/en-us/library/windows/desktop/ms682512(v=vs.85).aspx). 응용 프로그램이 프로세스를 작성하면 위의 붙여 넣은 링크의 예제 코드 에서처럼 프로세스가 종료 될 때까지 기다릴 수 있습니다. 프로세스 목록을 질의 할 필요가 없습니다. – BitTickler

+0

왜 PID 대신 프로세스 이름을 사용하지 않으시겠습니까? 프로세스 이름이이 목적에 더 적합합니다. –

+0

"실행 중"과 "응답하지 않음"을 어떻게 정의합니까? 그 과정은 존재합니까? CPU를 소비하고 있습니까? I/O를 수행하고 있습니까? 데이터베이스를 업데이트합니까? 활동에 응답합니다 (예 : 뮤텍스를 토글하거나 메시지 대기열을 통해 메시지를 보내는 중입니까? – HABO

답변

0

이름으로 프로세스를 종료하려면 다음과 같이하십시오.

private void TerminateAll() 
    { 
     foreach (var process in Process.GetProcessesByName("exenamewithoutext")) 
     { 
      process?.Kill(); 
     } 
    } 

다음은 코드를 리팩토링하는 아이디어입니다.

public class ProcessRunner 
{ 
    /// <summary> 
    /// Gets or sets the running process. 
    /// </summary> 
    private Process RunningProcess { get; set; }  

    /// <summary> 
    /// The exepath of the process. 
    /// </summary> 
    private readonly string exePath; 

    public ProcessRunner(string exePath) 
    { 
     this.exePath = exePath; 
    } 

    /// <summary> 
    /// Runs the specified executable path. 
    /// </summary> 
    /// <param name="exePath">The executable path.</param> 
    public void Run() 
    { 
     var processInfo = new ProcessStartInfo { Arguments = "<Your Args>", FileName = exePath, WindowStyle = ProcessWindowStyle.Normal }; 
     try 
     { 
      this.RunningProcess = Process.Start(processInfo); 
     } 
     catch (Exception exception) 
     { 
      throw new ProcessRunnerException(exception.Message); 
     } 
    } 

    /// <summary> 
    /// Terminates this instance. 
    /// </summary> 
    public void Terminate() 
    { 
     if (this.RunningProcess != null) 
     {    
      this.RunningProcess.Kill(); 
      this.RunningProcess.Dispose(); 
     } 
    } 
} 


public class ProcessManager 
{ 
    private readonly IList<ProcessRunner> MyProcessors{ get; } 

    public ProcessManager() 
    { 
     MyProcessors = new List<ProcessRunner>(); 
     MyProcessors.Add(new ProcessRunner("myexe.exe")); // Add as many as you want. 
    } 

    public void RunAll() 
    { 
     foreach(var proc in MyProcessors) 
     { 
      proc.Run(); 
     } 
    } 

    public void KillAll() 
    { 
     foreach(var proc in MyProcessors) 
     { 
      proc.Terminate(); 
     } 
    } 
}