MSMQ en Compact-Framework
Por Unai Zorrilla Castro
Descargar ejemplos de este artículo (1 MB).
Contenido
Introducción
System.Messaging
Instalación de MSMQ en el cliente Pocket PC
Implementando una aplicación con MSMQ
Conclusión
Introducción
Hace ya un tiempo leí por primera vez el termino OCC; éste hacía referencia a las aplicaciones ocasionalmente conectadas (Occasionaly Connected Applications); al leer la documentación sobre MSMQ en Compact Framework se incidía mucho en este término, ¿Porqué?
System.Messaging
Para la comunicación entre procesos en una misma o distinta máquina no siempre se requiere tener presente un vínculo de comunicación (comunicación ocasional); MSMQ representa esta filosofía junto con la asincronía asociada a la misma. La llegada de MSMQ a Compact Framework es una gran noticia para todos aquellos desarrolladores que demandaban este tipo de soluciones en movilidad y que no disponían de los medios en la plataforma.
System.Messaging es el espacio de nombres donde tenemos el conjunto de clases para implementar soluciones con MSMQ. La clase básica de trabajo con MSMQ es MessageQueue, que está contenida en este espacio de nombres y nos facilita tanto el envío como la recepción de mensajes asíncronos.
El primer paso para la construcción de una aplicación con mensajería asíncrona comienza con la instalación de MSMQ en el dispositivo móvil, proceso que veremos a continuación.
Instalación de MSMQ en el cliente Pocket PC
Si bien el proceso de instalación no es sencillo, una vez hecho el primero, el resto nos resultarán más fáciles. Empezaremos por crear una nueva solución Windows Forms para Pocket PC (Ver Figura 1):
Figura 1. Volver al texto.
El primer paso será incorporar los componentes MSMQ necesarios a nuestra solución; para ello realizamos la siguiente tarea: Los componentes necesarios para realizar la instalación de MSMQ en nuestro cliente se encuentran en la ruta C:\Program Files\Microsoft Visual\ Studio8\SmartDevices\SDK\SDKRedist\MSMQ\Arm4. Para agregarlos, nos situamos en la ventana de soluciones; sobre la solución hacemos clic en Add exisiting Item y seleccionamos todos los archivos que se encuentran en la ruta anterior (Ver Figura 2):
Figura 2. Volver al texto.
Con esto tendremos en nuestra solución todos los componentes necesarios para la instalación de MSMQ. Crearemos el método de instalación de los componentes en nuestro PocketPC; para ello agregamos un Label y un Button, el Clic del botón llamará a nuestro método de instalación, al cual llamaremos StartMSMQ():
private const string MSMQ_ADM = @"\windows\msmqadm.exe"; private const string MSMQ_DRIVER_REG = @"Drivers\BuiltIn\MSMQD"; private void btInstallMSMQ_Click(object sender, EventArgs e) { StartMSMQ(); } private void StartMSMQ () { CopyFilesRequired(); if (!(CreateProcess(MSMQ_ADM, "status"))) { CreateProcess(MSMQ_ADM, "register cleanup"); if (CreateProcess(MSMQ_ADM, "register install")) MessageBox.Show("Drivers instalados correctamente"); else { MessageBox.Show("Error al instalar MSMQ"+ GetLastError().Tostring()); return; } if (CreateProcess(MSMQ_ADM, "register")) MessageBox.Show("MSMQ registrado"); else MessageBox.Show("Error = " + GetLastError().Tostring()); if (CreateProcess(MSMQ_ADM, "enable binary")) MessageBox.Show("Activado"); else { MessageBox.Show("Error = " + GetLastError().Tostring()); return; } if (CreateProcess(MSMQ_ADM, "start")) MessageBox.Show("Comienzo de MSMQ"); else { IntPtr handle = ActivateDevice(MSMQ_DRIVER_REG, 0); CloseHandle(handle); if (CreateProcess(MSMQ_ADM, "status")) MessageBox.Show("MSMQ corriendo"); else MessageBox.Show("Error = " + GetLastError().Tostring()); } } else MessageBox.Show("MSMQ ya esta corriendo"); } private static void CopyFilesRequired() { string[] fileList = {"msmqadm.exe", "msmqadmext.dll", "msmqd.dll","msmqrt.dll", "visadm.exe" }; string path=Path.GetDirectoryName (System.Reflection.Assembly.GetExecutingAssembly().GetName().Code Base) + "\\"; for (int i = 0; i < fileList.Length; i++) { if (!File.Exists(@"\windows\" + fileList[i])) { File.Copy(path + fileList[i], @"\windows\" + fileList[i]); File.Delete(path + fileList[i]); } } } public class ProcessInfo { public IntPtr hProcess; public IntPtr hThread; public Int32 ProcessId; public Int32 ThreadId; } [DllImport("CoreDll.DLL", SetLastError = true)] private extern static int CreateProcess(string imageName, string cmdLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, Int32 boolInheritHandles, Int32 dwCreationFlags, IntPtr lpEnvironment, IntPtr lpszCurrentDir, IntPtr lpsiStartInfo, ProcessInfo pi); [DllImport("CoreDll.dll")] private extern staticInt32 GetLastError(); [DllImport("CoreDll.dll")] private extern static Int32 GetExitCodeProcess(IntPtr hProcess, out Int32 exitcode); [DllImport("CoreDll.dll")] private extern static Int32 CloseHandle(IntPtr hProcess); [DllImport("CoreDll.dll")] private extern static IntPtr ActivateDevice( string lpszDevKey, Int32 dwClientInfo); [DllImport("CoreDll.dll")] private extern static Int32 WaitForSingleObject(IntPtr Handle,Int32 Wait); public static bool CreateProcess(string ExeName, string CmdLine) { Int32 INFINITE; unchecked { INFINITE = (int)0xFFFFFFFF; } ProcessInfo pi = new ProcessInfo(); if (CreateProcess(ExeName, CmdLine, IntPtr.Zero, IntPtr.Zero, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero,pi) == 0) return false; WaitForSingleObject(pi.hProcess, INFINITE); Int32 exitCode; if (GetExitCodeProcess(pi.hProcess, out exitCode) == 0) { MessageBox.Show("Error en GetExitCodeProcess"); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); return false; } CloseHandle(pi.hThread); CloseHandle(pi.hProcess); if (exitCode != 0) return false; else return true; }
Una vez terminada la implementación de StartMSMQ , generamos la solución en el emulador de Pocket PC 2003 y hacemos clic en Instalar. Una vez instalados, detenemos la depuración conservando el estado del emulador (Ver Figura 3):
Figura 3. Volver al texto.
Implementando una aplicación con MSMQ
En el paso anterior hemos visto cómo instalar MSMQ en el cliente, por lo tanto estamos en posición de empezar la implementación de nuestra primera aplicación. Agregamos al formulario los siguientes elementos:
2 etiquetas
Enviar
Recibir
2 cajas de texto
Caja de texto enviar
Caja de texto recibir
2 botones
Botón enviar
Botón recibir
La estructura del formulario queda de la siguiente forma (Ver Figura 4):
Figura 4. Volver al texto.
Como ejemplo de implementación vamos a instanciar el objeto de acceso a las colas de MSMQ (MessageQueue) y realizar los procesos de envío y recepción de mensajes asíncronos. En el método Enviar comprobaremos la existencia de la cola de trabajo, creándola si es necesario:
private void btSend_Click(object sender, EventArgs e) { if (deviceQ == null) { string qName = @".\Private$\myQ"; if (!MessageQueue.Exists(qName)) MessageQueue.Create(qName); deviceQ = new MessageQueue(qName); } deviceQ.Send(txtSend.Text); }
En el método Recibir esperamos por un mensaje en la cola de mensajes; una vez recibido se recupera su cuerpo y se muestra en la caja de texto correspondiente:
private void btRecv_Click(object sender, EventArgs e) { Message msg = deviceQ.Receive(); string strMsg = (string)msg.Body; txtRecv.Text = strMsg; }
Conclusión
La nueva versión de la plataforma .Net nos trae muchas novedades, tanto en el entorno de desarrollo como en la mejora de técnicas existentes y nuevas funcionalidades. Sin lugar a dudas la llegada de MSMQ a Compact Framework es algo que muchos estábamos esperando y que por fin tenemos a nuestro alcance.
Unai Zorrilla Castro está radicado en Ourense, España; es Analista Programador de soluciones .NET especializado en aplicaciones C# y actualmente se encarga del desarrollo de componentes y herramientas .net orientadas al desarrollo de aplicaciones para la gestión y manejo de comunicaciones (IVR, FOIP, VOIP, TTS).