Vous êtes sur la page 1sur 12

1 de 12

Ejecucin de procesos
Finalizacin de procesos
Monitorizacin de procesos
Operaciones de E/S

Ejecucin de procesos
La clase System.Diagnostics.Process permite crear y monitorizar procesos (accediendo a la
informacin que se visualiza en el Administrador de Tareas de Windows).
El mtodo Process.Start() equivale a la llamada ShellExecute del API de Windows (Win32) y
es el que deberemos utilizar para lanzar un proceso. Los parmetros del proceso se especifican
mediante un objeto de la clase ProcessStartInfo. Al encapsular una llamada al shell de Windows,
el mtodo Start tambin podemos usarlo para abrir un fichero de cualquier tipo de los que tengan
acciones asociadas en el registro de Windows.
Ejecucin de procesos

2 de 12

Probar las distintas formas de lanzar un proceso escribiendo la respuesta al evento


Click de cada botn de la ventana que se muestra en la imagen de encima:
Lanzar proceso:
System.Diagnostics.Process.Start("iexplore.exe");
Lanzar proceso con parmetros:
string proceso = "iexplore.exe";
string args = "http://elvex.ugr.es/decsai/Csharp/";
System.Diagnostics.Process.Start("iexplore.exe", args);
Lanzar un proceso utilizando ProcessStartInfo:
using System.Diagnostics;
...
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "iexplore.exe";
info.Arguments = "http://elvex.ugr.es/decsai/CSharp/";

3 de 12

info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized;
Process.Start(info);
Lanzar el proceso adecuado para un fichero cualquiera:
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.InitialDirectory = "c:\\" ;
openFileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
openFileDialog.FilterIndex = 2 ;
openFileDialog.RestoreDirectory = true ; // Vuelve al directorio actual
if (openFileDialog.ShowDialog() == DialogResult.OK) {
System.Diagnostics.Process.Start(openFileDialog.FileName);
}
Abrir una URL:
System.Diagnostics.Process.Start("http://elvex.ugr.es/decsai/Csharp/");
Uso de los verbos del shell:
using System.Diagnostics;
...
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "Ade.jpg";
info.WorkingDirectory = "f://";
info.Verb = "edit"; // vs. "open" || "print"
Process.Start(info);
//
//
//
//
//
//
//

Verbos comunes
-------------open
Abre un ejecutable, documento o carpeta
edit
Edita un documento
print
Imprime un documento
explore Explora una carpeta
find
Inicia una bsqueda en el directorio especificado

4 de 12

RECOMENDACIN: Cuando se utiliza el mtodo Process.Start, tambin se debera llamar siempre


al mtodo Process.Close para liberar la memoria asociada al objeto de tipo Process.

Finalizacin de procesos
En los ejemplos anteriores, si quisiramos que nuestra aplicacin detuviese su ejecucin hasta que el
proceso lanzado finalizase su ejecucin, slo tendramos que llamar al mtodo WaitForExit:

Process proceso = Process.Start(...);


proceso.WaitForExit();
proceso.Close();

La espera podra hacerse por un perodo de tiempo limitado si utilizamos un parmetro en la llamada
al mtodo WaitForExit:
Ejecucin invisible de comandos MS-DOS

Process proceso = new Process()


string
string

salida = Application.StartupPath + "/output.txt";


path
= System.Environment.GetFolderPath
(Environment.SpecialFolder.System);

proceso.StartInfo.FileName = "cmd.exe";
proceso.StartInfo.Arguments =
"/C dir \""+path+"\" >> \"" + salida +"\" && exit";

5 de 12

proceso.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
proceso.StartInfo.CreateNoWindow = true;
proceso.Start()
proceso.WaitForExit(1000);
if (!proceso.HasExited()) {
proceso.Kill();
} else {
...
}

// 1 segundo de timeout

// Finalizamos el proceso

Adems, tambin podemos detectar cundo finaliza un proceso que hayamos lanzado si empleamos
el manejador de eventos Exited de la clase Process. De esta forma, no tenemos por qu bloquear
la ejecucin de nuestra aplicacin mientras esperamos la terminacin de un proceso:
Evento asociado a la terminacin de un proceso

Process proceso = new Process()


...
proceso.Exited += new EventHandler(ExitHandler);
proceso.Start()
...
El mtodo ExitHandler se encarga de realizar las tareas
necesarias al finalizar la ejecucin del proceso, como por
ejemplo:

public void ExitHandler(object sender, EventArgs e)


{
Process proceso = (Process) sender;
MessageBox.Show ( "PID: " + proceso.Id
+ System.Environment.NewLine

6 de 12

+ "Hora: " + proceso.ExitTime


+ System.Environment.NewLine
+ "Cdigo: " + proceso.ExitCode );
proces.Close();
}

La clase Process tambin nos permite provocar la terminacin de un proceso. sta se puede
realizar explcitamente utilizando los mtodos Kill() y CloseMainWindow(), siendo este ltimo el
mtodo recomendado, pues equivale a que el usuario de la aplicacin cierre sta de la forma usual.
Es decir, CloseMainWindow solicita cerrar la aplicacin como si el propio usuario cerrase la ventana
principal de la aplicacin (lo cual puede provocar la aparicin de mensajes de la aplicacin), mientras
que Kill finaliza el proceso "por las bravas", pudiendo ocasionar la prdida de datos que no hayan
sido previamente guardados.
En la siguiente seccin veremos cmo se puede forzar la finalizacin de un proceso y tambin
aprenderemos a acceder a la informacin relativa a los procesos que se estn ejecutando en una
mquina Windows (la misma informacin que figura en el Administrador de Tareas de Windows).

Monitorizacin de procesos
Monitor de procesos

7 de 12

Creamos una aplicacin Windows a la que denominamos WindowMonitor, cuyo


formulario principal (Text="Procesos del sistema") contiene los siguientes
componentes:
ListBox listProcesses (ScrollAlwaysVisible=true).
TextBox textInfo (BackColor=Info; Multiline=true).
Button buttonClose (Text="WindowClose"; ForeColor=ForestGreen).
Button buttonKill (Text="Kill"; ForeColor=DarkRed).
Label labelWarning (TextAlign=MiddleCenter; Text="OJO! Kill puede
ocasionar la prdida de datos al forzar la terminacin de un proceso...").
Al cargar el formulario, rellenamos la lista de procesos del sistema (evento
FormLoad):

Process[] procesos = Process.GetProcesses();

8 de 12

listProcesses.Items.AddRange(procesos);
Cuando el usuario selecciona un proceso concreto, mostramos informacin detallada
acerca del proceso seleccionado (evento SelectedIndexChanged del ListBox):

Process selected = (Process) listProcesses.SelectedItem;


textInfo.Clear();
if (selected!=null)
textInfo.Lines = new string[] {
"Proceso: " + selected.ProcessName,
"PID: " + selected.Id,
// "Mquina: " + selected.MachineName,
"Prioridad: " + selected.PriorityClass,
"Uso de memoria: " + selected.WorkingSet + " bytes",
// selected.PagedMemorySize
// selected.VirtualMemorySize
"Tiempo de CPU: " + selected.TotalProcessorTime,
"Hora de inicio: " + selected.StartTime,
"Mdulo principal: " + selected.MainModule.FileName
// selected.MainWindowTitle
};
Finalmente, programamos la respuesta de la aplicacin correspondiente a los dos
botones de nuestra interfaz:

// Fuerza la finalizacin del proceso


// (puede provocar la prdida de datos)
private void buttonKill_Click(object sender, System.EventArgs e)
{
Process selected = (Process) listProcesses.SelectedItem;
if (selected!=null)
selected.Kill();
}

9 de 12

// Solicita la terminacin de un proceso


// (como si el usuario solicitase cerrar la aplicacin)
private void buttonClose_Click(object sender, System.EventArgs e)
{
Process selected = (Process) listProcesses.SelectedItem;
if (selected!=null) {
if (selected.Id==Process.GetCurrentProcess().Id)
MessageBox.Show("Ha decidido finalizar la aplicacin actual");
selected.CloseMainWindow();
}

NOTA: En la barra de herramientas [toolbox], dentro del apartado "Components", podemos


encontrar un componente denominado Process que nos permite trabajar con procesos de forma
visual.

Operaciones de E/S
En ocasiones nos interesa que la entrada de un proceso provenga directamente de la salida de otro
proceso. Enviar la salida a un fichero y despus leer el fichero no siempre es la mejor opcin, ya que
el uso de "pipes" resulta mucho ms eficiente para conectar distintos procesos. La clase Process
nos permite redireccionar los canales de E/S estndar (StdIn, StdOut y StdErr). Slo tenemos que
fijar
a
"true"
las
propiedades
RedirectStandardInput,
RedirectStandardOutput
y
RedirectStandardError, tras lo cual podemos acceder a las propiedades StandardInput,
StandardOutput y StandardError del proceso (objetos de tipo StreamReader y StreamWriter).
Una observacin: Process.Start utiliza por defecto la funcin ShellExecute del API Win32. Cuando
utilicemos redireccionamientos, la propiedad ProcessStartInfo.UseShellExecute debe estar
puesta a "false" antes de invocar al mtodo Process.Start.

10 de 12

Process proceso = new Process();


proceso.StartInfo.FileName = "cmd.exe";
proceso.StartInfo.UseShellExecute = false;
proceso.StartInfo.CreateNoWindow = true;
proceso.StartInfo.RedirectStandardInput = true;
proceso.StartInfo.RedirectStandardOutput = true;
proceso.StartInfo.RedirectStandardError = true;
proceso.Start()
StreamWriter sIn = proceso.StandardInput;
sIn.AutoFlush = true;
StreamReader sOut = proceso.StandardOutput;
StreamReader sErr = proceso.StandardError;
sIn.Write("dir c:\" + System.Environment.NewLine);
sIn.Write("exit" + System.Environment.NewLine);
string output = sOut.ReadToEnd();
sIn.Close();
sOut.Close();
sErr.Close();
proceso.Close();
MessageBox.Show(output);

Para los programas que no utilizan StdIn se puede utilizar el mtodo SendKeys para simular la
pulsacin de teclas:
Acceso al Bloc de Notas con SendKeys

Curso de C# - Procesos

11 de 12

Process proceso = new Process();


proceso.StartInfo.FileName
= "notepad";
proceso.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
proceso.EnableRaisingEvents
= true;
proceso.Start();
proceso.WaitForInputIdle(1000); // 1 segundo de timeout
if (proceso.Responding)
System.Windows.Forms.SendKeys.SendWait
("Texto enviado con System.Windows.Forms.SendKeys");

Cualquier combinacin de teclas se puede enviar con SendKeys, lo que permite hacer prcticamente
cualquier cosa con una aplicacin Windows (siempre que nos aseguremos de que es la aplicacin
activa, la que tiene el foco).
No se pueden utilizar SendKeys hasta que no se haya creado y se visualice la ventana principal de
la
aplicacin,
por
lo
que
en
el
ejemplo
de
arriba
se
emple
el
mtodo
Process.WaitForInputIdle, que espera hasta que la aplicacin pueda aceptar entradas por
parte del usuario y cuyo funcionamiento es anlogo a Process.WaitForExit.
Acceso a recursos nativos de Windows
Con SendKeys se puede simular la pulsacin de cualquier combinacin de
teclas. No obstante, SendKeys se limita a enviar eventos de pulsacin de teclas
a la aplicacin que est activa en cada momento. Y no existe ninguna funcin
estndar en .NET que nos permita establecer la aplicacin activa, pero s en el
API nativo de Windows.
El API de Windows incluye una gran cantidad de funciones (no mtodos), del
orden de miles. En el caso que nos ocupa, podemos recurrir a las funciones
FindWindow y SetForegroundWindow del API Win32 para establecer la
aplicacin activa. Como estas funciones no forman parte de la biblioteca de
clases .NET, tenemos que acceder a ellas usando los servicios de

12 de 12

interoperabilidad con COM. Estos servicios son los que nos permiten acceder a
recursos nativos del sistema operativo y se pueden encontrar en el espacio de
nombres System.Runtime.InteropServices.
Para poder usar la funcin SetForegroundWindow, por ejemplo, tendremos que
escribir algo parecido a lo siguiente:

using System.Runtime.InteropServices;
...
[DllImport("User32",EntryPoint="SetForegroundWindow")]
private static extern bool SetForegroundWindow(System.IntPtr hWnd);
Una vez hecho esto, ya podemos acceder a la funcin SetForegroundWindow
como si de un mtodo ms se tratase:

Process proceso = ...


if (proceso.Responding) {
SetForegroundWindow(proceso.MainWindowHandle);
SendKeys.SendWait("Sorpresa!!!");
SetForegroundWindow(this.Handle);
}
Y ya podemos hacer prcticamente cualquier cosa con una aplicacin Windows,
controlndola desde nuestros propios programas.

Vous aimerez peut-être aussi