私はいくつかのプロセスを起動するアプリケーションを持っています。このアプリケーションの目的は、一度起動されたかどうかを監視し、起動していない場合は監視し、応答しない場合はプロセスを強制終了し、実行されていない場合は再起動します。アプリケーションが最初に起動することを知っているそれぞれのプロセスを実行し、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
ステートメントにあります。
もっと効果的な方法がありますか?
アプリケーションがいくつかのインスタンス(ただし、異なる初期化引数付き)を起動、その名前でプロセスをキャプチャが推奨されていない、そのような場合にのみ使用してコマンドラインでそれらを区別する必要があり、単一の実行可能ファイルから追加の明確化
プロセスは実行されました。さらに、プロセスが2つの基準(最初はプロパティーProcess.Responding
)で応答しているかどうかを確認し、2番目のすべてのプロセスが時々、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
}
}
プロセスハンドルは待機可能なオブジェクトです。 (例:https://msdn.microsoft.com/en-us/library/windows/desktop/ms682512(v=vs.85).aspx)。アプリケーションがプロセスを作成する場合は、上に貼り付けたリンクのサンプルコードで完了したように、プロセスが終了するのを待つことができます。プロセスリストを照会する必要はありません。 – BitTickler
なぜPIDの代わりにプロセス名で行かないのですか?プロセス名はこの目的に適しています。 –
"実行中"と "応答しません"をどのように定義しますか?プロセスは存在しますか? CPUを消費していますか? I/Oを実行していますか?データベースを更新しますか?アクティビティに応答します(例:ミューテックスをトグルするか、メッセージキューを介してメッセージを送信しますか? – HABO