Desarrollamos una utilidad de línea de comando en C# (C Sharp), válida para ser ejecutada por otras aplicaciones externas, que admite envío de título de ventana y pulsación de teclas. La aplicación de consola buscará la ventana (aplicación) en ejecución por el título de la ventana, si la encuentra y la puede enfocar, le enviará la pulsación de teclas establecida por parámetro. Como ejemplo lanzamos esta app de línea de comando desde una aplicación Delphi, haciendo una llamada de teléfono a un número marcado en la aplicación Cisco IP Communicator.
- Aplicación C# que envía pulsación de teclas a aplicación externa.
- Ejemplo de uso de aplicación de consola C# que envía pulsación de teclas con aplicación Delphi.
- La aplicación en funcionamiento para mostrar la ventana de Cisco IP Communicator y marcar una extensión de teléfono.
Aplicación C# que envía pulsación de teclas a aplicación externa
A continuación mostramos el código fuente completo en C# de la aplicación de consola (Console Application) que permite recibir los siguientes parámetros:
- Tipo de búsqueda de la aplicación externa abierta. Las opciones:
- Titulo_Ventana: buscará la aplicación externa abierta por el título de la ventana (se puede consultar en el Administrador de tareas). Por ejemplo, para el caso de la aplicación Cisco IP Communicator el título de la ventana (establecido en el parámetro siguiente, será «Cisco IP Communicator»).
- Nombre_Clase: buscará la aplicación externa abierta por el nombre de la clase.
- Nombre de la ventana o bien de la clase: en este segundo parámetro introduciremos el nombre de la ventana/clase de la aplicación abierta a la que queramos enviar la pulsación de teclas. Si lleva espacios lo estableceremos entrecomillado.
- Teclas a enviar a aplicación externa: en el tercer parámetro estableceremos las teclas que se enviarán a la aplicación externa abierta, si se incluyen espacios, entrecomillaremos este parámetro.
- llamar: último parámetro, opcional. Si se incluye la aplicación enviará al final de las teclas indicadas en el parámetro anterior, también la tecla INTRO.
La aplicación de consola en C# devolverá los siguientes códigos según el resultado de la ejecución:
- 0: la ejecución de la aplicación de consola, la búsqueda de la aplicación externa, el enfoque y el envío de teclas ha sido correcto.
- 1: error, no se ha encontrado la ventana de la aplicación externa abierta.
- 2: error, se ha producido cualquier otro error.
- 3: error, la ventana de la aplicación externa se ha encontrado pero no ha podido ser enfocada (traída al frente).
El código fuente completo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
using System; using System.Runtime.InteropServices; using System.Windows.Forms; namespace EnviarTeclas { internal class Program { [DllImport("user32.dll")] static extern long SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("User32.dll")] public static extern bool ShowWindow(IntPtr handle, int nCmdShow); static void Main(string[] args) { //Parámetros /* 1 -> Titulo_Ventana o bien Nombre_Clase: para tipo de búsqueda de aplicación externa 2 -> Nombre de la ventana o bien de la clase 3 -> Teclas a enviar a aplicación externa 4 -> "llamar" -> añade un INTRO a las teclas enviadas */ //Valores que devuelve la app de consola /* 0 -> Ejecución correcta 1 -> Error, no se ha encontrado la ventana de la aplicación a la que se envían las teclas 2 -> Error, otro error 3 -> Error, la ventana se ha encontrado pero no ha podido ser enfocada (traída al frente) */ //Comprobamos si se han pasado parámetros if (args.Length >= 3) { //Leemos el parámetro 1 - Tipo de búsqueda string tipoBusqueda = args[0]; string tituloVentanaClase = args[1]; string teclas = args[2]; bool llamar = false; //Si se le ha pasado el parámetro "llamar", para //añadir la pulsación de la tecla INTRO (para que marque y llame) if (args.Length > 3) { if (args[3] == "llamar") llamar = true; } //Console.WriteLine("Buscando ventana Cisco IP Communicator..."); IntPtr handle = IntPtr.Zero; if (tipoBusqueda == "Titulo_Ventana") handle = FindWindow(null, tituloVentanaClase); if (tipoBusqueda == "Nombre_Clase") handle = FindWindow(tituloVentanaClase, null); if (handle == IntPtr.Zero) { //Si no se ha encontrado la ventana por el título //Console.WriteLine("Ventana Cisco IP Communicator no encontrada..."); //Console.ReadKey(); Environment.ExitCode = 1; } else { //Console.WriteLine("Ventana Cisco IP Communicator encontrada, enviando teclas..."); //Traemos ventana al frente ShowWindow(handle, 9); long traidaAlFrente = SetForegroundWindow(handle); //Si se ha podido "traer al frente) (enfocar) if (traidaAlFrente != 0) { //Enviamos la pulsación de teclas try { SendKeys.SendWait(teclas); if (llamar) SendKeys.SendWait("{ENTER}"); //Console.WriteLine("Teclas enviadas a Cisco IP Communicator"); Environment.ExitCode = 0; } catch (Exception e) { //Error al enviar teclas a aplicación Console.WriteLine("Se ha producido el siguiente error al enviar las teclas a " + tituloVentanaClase); Console.WriteLine(e.Source + " " + e.Message); Console.ReadKey(); Environment.ExitCode = 2; } } else { Console.WriteLine("La aplicación " + tituloVentanaClase + " se ha encontrado pero NO se ha podido enfocar (trar al frente)."); Console.WriteLine("Pulse cualquier tecla para salir."); Console.ReadKey(); Environment.ExitCode = 3; } } } else { Console.WriteLine("No se han pasado parámetros (Tipo_Busqueda, Titulo_Ventana, teclas, llamar)."); Console.WriteLine("Pulse cualquier tecla para salir."); Console.ReadKey(); } } } } |
Ejemplo de uso de aplicación de consola C# que envía pulsación de teclas con aplicación Delphi
La aplicación de consola anterior, que una vez compilada genera el fichero EnviarTeclas.exe puede ser usada desde cualquier otra aplicación o script powershell, bat, etc.. Dado que se ejecuta desde la línea de comandos y se le pasan los parámetros indicados anteriormente.
A continuación mostramos un ejemplo de aplicación Delphi que lanza la aplicación C# anterior. Esta aplicación realiza una llamada de teléfono, usando Cisco IP Communicator. Desarrollada en Delphi, aunque el proceso es el mismo para cualquier otro lenguaje de progamación.
La aplicación Delphi ejecutará la aplicación de consola anterior, para pasarle el nombre de la aplicación Cisco IP Communicator, un número de teléfono y el parámetro «llamar» (para que envíe al final un INTRO y haga la llamada directamente).
La ventana de la aplicación Delphi tendrá este aspecto:
El código fuente de la ventana anterior de la aplicación en Delphi es:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
unit UnidadEnvioTeclas; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons; type TformEnvioTeclas = class(TForm) GroupBox1: TGroupBox; Label1: TLabel; Label2: TLabel; txtTelefono: TEdit; txtUsuario: TEdit; opMarcarLlamar: TCheckBox; txtInfo: TMemo; btLlamar: TBitBtn; btCerrar: TBitBtn; procedure btCerrarClick(Sender: TObject); procedure btLlamarClick(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormShow(Sender: TObject); private { Private declarations } public { Public declarations } end; var formEnvioTeclas: TformEnvioTeclas; implementation uses UnidadProcedimientos; {$R *.dfm} procedure TformEnvioTeclas.btCerrarClick(Sender: TObject); begin close; end; procedure TformEnvioTeclas.btLlamarClick(Sender: TObject); var appEnviarTeclas, extension : string; ejecutable, teclas, tipoBusquedaAppExterna, tituloVentanaAppExterna : string; resultado : integer; begin obtenerValorParametro('enviar_teclas_aplicacion_teclas', ejecutable, teclas); obtenerValorParametro('enviar_teclas_titulo_ventana_tipo_busqueda', tipoBusquedaAppExterna, tituloVentanaAppExterna); appEnviarTeclas := IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName)) + ejecutable; extension := txtTelefono.Text; if extension <> '' then begin if FileExists(appEnviarTeclas) then begin teclas := reemplazarTexto (teclas, '[[Extensión]]', extension); if opMarcarLlamar.Checked then teclas := teclas + ' llamar'; resultado := ejecutarEsperarResultado(appEnviarTeclas + ' ' + tipoBusquedaAppExterna + ' ' + tituloVentanaAppExterna + ' ' + teclas, SW_NORMAL); case resultado of 0 : //Ejecución correcta, insertamos la llamada en log de incidencia begin insertarLogIncidencia(vtCodigoUsuario, 'Llamar', Now, tag, now, now, 'Llamada de teléfono a extensión ' + txtTelefono.Text, 0, 'N', 'Realizada llamada de teléfono enviando teclas: ' + chr(13) + chr(13) + teclas); close; end; 1: //error, no se ha encontrado la ventana de la aplicación a la que se envían las teclas begin MessageDlg ('No se ha encontrado abierta la aplicación [' + tituloVentanaAppExterna + '] para enviar la teclas [' + teclas + ']. Debe tenerla abierta para el correcto funcionamiento de esta acción.', mtWarning, [mbok], 0); end; 2: //error, otro error begin MessageDlg ('No se han podido enviar las teclas [' + teclas + '] a la aplicación [' + tituloVentanaAppExterna + ']. Se ha producido un error, contacte con su departamento de TIC.', mtWarning, [mbok], 0); end; 3: //error, la aplicación se ha encontrado pero no ha podido ser enfocada (traída al frente) begin MessageDlg ('La aplicación [' + tituloVentanaAppExterna + '] se ha encontrado pero no ha podido ser enfocada (traída al frente).', mtWarning, [mbok], 0); end; 40064448: begin MessageDlg ('No se ha podido ejecutar la aplicación "EnvioTeclas.exe", ' + 'puede que necesite .NET Framework 4.0 o superior.', mtWarning, [mbok], 0); end; else MessageDlg ('Resultado inesperado al enviar teclas [' + teclas + '] a [' + tituloVentanaAppExterna + '].', mtWarning, [mbok], 0); end; end else MessageDlg('Para usar esta función necesita disponer del ejecutable ' + 'EnviarTeclas.exe en la carpeta de la aplicación.', mtWarning, [mbok], 0); end else MessageDlg('No ha indicado una extensión de teléfono para llamar.', mtWarning, [mbok], 0); end; procedure TformEnvioTeclas.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := caFree; end; procedure TformEnvioTeclas.FormShow(Sender: TObject); begin if txtTelefono.Text <> '' then btLlamar.SetFocus; end; end. |
La aplicación en funcionamiento para mostrar la ventana de Cisco IP Communicator y marcar una extensión de teléfono
La aplicación de ejemplo en Delphi (puede ser cualquier otra) ejecutará el fichero EnviarTeclas.exe (generado con la aplicación de consola C#) y le pasará los siguientes parámetros:
EnviarTeclas.exe Titulo_Ventana «Cisco IP Communicator» 968505050 llamar
Añadirá el parámetro «llamar» si se ha marcado el check «Marcar y llamar»:
La aplicación ejecutada de consola EnviarTeclas.exe buscará la aplicación «Cisco IP Communicator», si la encuentra abierta y puede traerla al frente (enfocarla), enviará la pulsación de teclas «968505050» y al pasarle el parámetro «llamar», también enviará la pulsación de la tecla INTRO para que efectúe la llamada al número tecleado: