VFP Por Maurice de Beijer http://www.theproblemsolver.nl/ s ource.zip
Desde la salida de Visual FoxPro versin 5 podemos construir Servidores COM. Esto ha creado un nuevo rango de posibilidades a Visual FoxPro y da a los desarrolladores de VFP un nuevo campo para crear soluciones. Sin embargo, los servidores COM tienen sus dificultades y problemas a la hora de desarrollarlos.
El problema a la hora de desarrollar Servidores COM El principal problema viene del hecho de que el desarrollador de Servidores COM tiene que escribir el cdigo, compilarlo en un .EXE .DLL y ejecutar le programa cliente para probarlo. Esto significa que uno siempre ejecuta cdigo que est compilado y bajo el control de VFP. No hay forma de usar el depurador o inspeccionar el valor de las variables usadas. Si se produce un bug de algn tipo en el cdigo fuente del servidor COM la prueba fallara o se entregara un cdigo de error a la aplicacin cliente. Siempre que esto suceda el desarrollador tiene que cambiar el fuente del servidor COM, recompilarlo y ejecutar el cliente de nuevo.
Figura 1: Fallo en un Servidor COM con una ventanita de error que ayuda muy poco.
Comprobar el valor de las variables se puede hacer slo aadiendo cdigo extra al servidor COM y las respuestas redirigirlas a la pantalla o a un archivo log. Una forma de resolver este problema es probar el servidor COM como un objeto normal de FoxPro creandolo en el entorno de desarrollo de Visual FoxPro. Sin embargo, esto deja de ser una solucin practica ya que Visual FoxPro no puede simular cada tipo de aplicacin cliente igualmente bien. De la misma forma los servidores COM que se usan en los scripts de las pginas activas son dificiles de depurar ya que es imposible, en el entorno de Visual FoxPro simular los objetos nativos de ASP. Compara el desarrollo de los servidores COM al poder de Visual FoxPro cuando se desarrollan aplicaciones interactivas. El desarrollador no tiene que construir un ejecutable, puede justo ejecutar el cdigo y abrir el depurador siempre que quiera. Si se produce un error de runtime, aparecer un dilogo con Cancelar, Suspend e Ignorar ofreciendo al desarrollador la opcin de suspender el programa e inspeccionar el entorno usando el depurador. Con frecuencia puedes cambiar algunas variables o parte del cdigo y ejecutarlo de nuevo.
Figura 2: Un mensaje de error que te da poca informacin con la posibilidad de suspender el programa e iniciar el depurador.
El resultado es que la productividad vara mucho a la hora de construir un servidor COM o una aplicacin normal en VFP. Una forma de poder solucionar esto sera el dar la opcin al desarrollador de poder ejecutar su cdigo del Servidor COM desde dentro de VFP de la misma forma a como hacer con un desarrollo interactivo normal.
Una rpida comparacin con Visual Basic Ejecutemos Visual Basic 6 para una rpida comparacin de cmo el desarrollo de una aplicacin web se realiza en Visual FoxPro y Visual Basic: 1. Inicia Visual Basic 6. 2. Crea un nuevo proyecto del tipo IIS Application. 3. Abre la clase WebClass1. 4. Establece un breakpoint en el mtodo WebClass_Start. 5. Pulsa F5 para ejecutar la aplicacin. 6. Para la aplicacin. 7. Cambia algo del cdigo. 8. Pulsa F5 para ejecutar de nuevo la aplicacin. Unas pocas grandes diferencias con Visual FoxPro son obvias de forma inmediata: 1. No hay necesidad de crear un web share o un directorio virtual en Internet Information Server. El entorno de desarrollo de Visual Basic 6 ha hecho esta parte de forma automtica. 2. Se lanza automticamente Internet Explorer y navega directamente al sitio web correcto. 3. Se abre el depurador de Visual Basic cuando se establece un breakpoint. 4. Cuando se para la aplicacin y el cdigo cambia, pulsar F5 no es bastnte para empezar de nuevo. No es necesario compilar una DLL o reiniciar el Internet Information Server. Slo con que se pudieran hacer las mismas cosas en VFP se ganara mucho en productividad.
Figura 3: Una clase en Visual Basic 6 El problema con Visual FoxPro Por qu, podras pensar, no puedo hacer las mismas cosas en VFP? El principal problema reside en la incapacidad de crear un objeto Servidor COM en el diseador de VFP en lugar de la runtima de VFP. Una forma mediante la que se podra evitar esto es mediante CreateObject(VisualFoxPro.Application) en lugar del COM server que ests tratando de crear y usar en las aplicaciones de VFP. Aunque esta opcin funciona tiene dos problemas. Primero, requiere un poco de cdigo en el cliente que es totalmente diferente del cdigo que usaras cuando est en produccin. En segundo lugar, empieza una sesin nueva de Visual FoxPro cada vez en lugar de reusar la session existente lo que produce problemas de compilacin cuando el fichero FXP est en uso por la otra sessin. Tomar el handle de un objeto en la session activa de Visual FoxPro no es posible. Otra forma de evitar esto es permitir a las sesiones comunicarse a travs de los archivos. Esto significa que debera haber un objeto en Visual FoxPro comprobando los archivos solicitados e iniciando una peticin cuando se encuentre. Esto tiene el inconveniente de que todas las comunicaciones se tienen que hacer a travs de los archivos del sistema y nosotros no podemos pasar objetos, como hace de forma nativa ASP al Servidor COM de Visual FoxPro.
La Solucin Con la salida de Visual FoxPro 7 Microsoft ha aadido soporte para la Active Accessibility en Visual FoxPro. La Active Accessibility est originalmente diseada para soportar a usuarios desactivados. Adems de su finalidad original, es tambin muy til para otros propsitos como la capacidad de crear herramientas de testeo con interfaz grfico. Visual FoxPro 7 viene con una herramienta, el Active Accessibility Test Harness, que hace justamente eso. Una de las muchas funciones del API del Active Accessibility es AccessibleObjectFromWindow. Esta funcin del API permite al desarrollador recupear un objeto IAccessible con la referencia a otro objeto. Una vez que tenemos una referencia a este objeto IAccessible podemos usar la otra funcin del API Active Accessibility para conseguir ms informacin. Una de estas funciones del API es el AccChild() que tiene la capacidad de devolver la referencia a un objeto de Visual FoxPro Application o _VFP. Una vez que se ha hecho esto todo lo que puedas hacer dentro del entorno de desarrollo de Visual FoxPro queda accesible para ti.
Listing 1: El mtodo usado para crear el objeto en tiempo de diseo en el entorno de Visual FoxPro.
************************************ Procedure GetDebugObject() as Object ************************************ * Return an object reference to a debugable copy of this COM server
Local loServer, loAcc, lnHwnd, lcGuid, loVFP, lcComLink loServer = Null #If c_ComDebugging loAcc = Null lnHwnd = 0 lcComLink = Addbs(JustPath(_vfp.ServerName)) + 'ComLink.dbf' If File(lcComLink) * There is an ComLink file with the required HWnd value of the design time VFP Use (lcComLink) In 0 Again Shared * Get the _VFP.hWnd value lnHwnd = ComLink.iHwnd * Close the table again Use In ComLink EndIf If lnHwnd <> 0 * We where able to load the required _VFP.hWnd value * Declare the required Active Accessibility function Declare Integer AccessibleObjectFromWindow In OleAcc Integer, Integer, String, Object @ * Convert the IAccecssible to a useable format lcGuid = Str2Guid(c_IAccGuid) * Try to get a handle on the IAccecssible interface of _VFP AccessibleObjectFromWindow(lnHWnd, c_ObjIdClient, lcGuid , @loAcc)
If Type('loAcc.AccChild(Int(2^31-1))') = 'O' * Retreive the _VFP reference from the IAccecssible object loVFP = loAcc.AccChild(Int(2^31-1))
If Type('loVFP.Name') = 'C' * We got the _VFP reference, use it to check if the status form exists If loVFP.Eval('Type([poStatus.chkDebug.Value]) = [L]') * The test succeeded, retreive the object loServer = loVFP.Eval('CreateObject([' + This.Class + '])') * Set any required properties of the debug server This.ConfigureDebugServer(loServer) EndIf EndIf EndIf EndIf #EndIf
* Return this server as the object to use if we are unable to reach the VFP design time environment loServer = Nvl(loServer, This)
Return loServer
Mediante el uso de las funciones descritas anteriormente, he creado una tecnica para copiar el servidor COM original que se ha creado y es almacenado en el entorno de diseo de VFP. La solucin tiene dos partes, una parte es un mtodo incluido en el Servidor COM original y la segunda es una utilidad de monitorizacin para el entorno de diseo de VFP. Para el entorno de desarrollo de Visual FoxPro he desarrollado un formulario que monitoriza el estado y permite al desarrollador ver cuando ha empezado una peticin y cuanto tiempo ocupa. Antes de mostrar el estado del formulario crea una tabla llamada ComLink con un simple registro y un campo en el directorio actual que contiene el valor del _VFP.hWnd de la session actual de Visual FoxPro. La aplicacin se asegura de que todas las libreras de clases requeridas y archivos de procedimientos se carguen de forma que los objetos requeridos puedan ser creados. El formulario de estado tambin incluye una opcin para lanzar el depurador al principio del siguiente request.
Figure 4: El formulario de estado del ASP Debido a que desarrollar componentes ASP es ms duro que desarrollar servidores COM normales decid crear un formulario separado para monitorizar que no solo permitiera al desarrollador iniciar el depurador al principio de la peticin sino tambin la opcin de aadir el contenido actual del objeto ASP al final de la pgina de response. Por el lado del servidor el principal mtodo envuelto es GetDebugObject(). Este mtodo primero comprueba si hay una tabla llamada ComLink en la misma situacin que el archivo ejecutable del COM. Si se encuentr se devuelve el valor hWnd y se usa con las funciones del Active Accessibility descritas anteriormente para conseguir una referencia a un Objeto Aplicacin de Visual FoxPro. Si esto es exitoso el mtodo _VFP.Eval() se usa entonces para crear un nuevo objeto de la misma clase que el Servidor COM. Este nuevo objeto, o si el intento falla por alguna razn el Servidor COM se devuelve al cliente. Para usar esto desde una aplicacin cliente la nica cosa que hay que hacer es aadir una lnea justo depus de la instruccin CreateObject(). Por ejemplo, lo siguiente en Visual Basic for Applications script en una hoja de Excel: Listing 2: El cdigo de Visual Basic for Applications utilizado en el Excel workbook.
Dim oDemo Set oDemo = CreateObject("ComDebug.ComDebug") Set oDemo = oDemo.GetDebugObject() oDemo.LoadData ActiveWorkbook
Se han aadido dos mtodos adicionales en la clase base como son el Init() y el Destroy(). Ambos se usan para registrar el inicio y el final de la peticin con el formulario de monitorizacin de estatus en tiempo de diseo. Depuracin de Componentes Active Server Pages La Depuracin de Servidores ASP COM es algo ms complejo que depurar un servidor COM usado por excel en una macro de VBA. La principal diferencia es que no puedes correr la aplicacin ASP desde dentro de VFP, necesitars asegurarte de que el directorio virtual del Internet Information Server virtual existe y est configurado adecuadamente. Esto no es nada nuevo pero puede ser facilmente automatizado usando los objetos del Windows ADSI. El formulario de estado usa los objetos ADSI para asegurarse de que hay un directorio virtual para el directorio especificado y determinar la URL que se debe usar para acceder a ese directorio. Si no se encuentra directorio virtual al desarrollador se le pregunta si quiere crear un nuevo directorio de Internet Information Server con la apropiada configuracin. He desarrollado este cdigo con la estructura de directorios en la cabeza que siempre uso para los sitios web. Podras quizas necesitar cambiarlo un poco para tus propositos. Uso una estructura de directorio con un directorio principal, por ejemplo AspDebug, para el proyecto. Este directorio siempre tiene un subdirectorio llamado WWWRoot. Este directorio se comparte con el Internet Information Server directorio virtual web bajo el nombre del directorio del proyecto principal. Por ejemplo: el directorio C:\AspDebug\WWWRoot se alzanza a travs del browser mediante el URL http://LocalHost/AspDebug.
Figure 5: La estructura del directorio que uso cuando desarrollo. El problema siguiente es la seguridad. En ASP el servidor COM se crea bajo la cuenta de IUSR_ account en lugar de la cuenta de usuario que has estado usando para desarrollar con Visual FoxPro. La cuenta IUSR es por defecto una cuenta con muchas restricciones. Para evitar estas restricciones es necesario cambiar la configuracin del Internet Information Server para la web y as evitar accesos annimos y permitir slo la autentificacin integrada en Windows. Esto tiene como resultdo que la pgina ASP y el componente COM se ejecutan bajo la cuenta actual de usuario enlugar de bajo el ISUR_ account. El formulario que monitoriza comprueba la autentificacin cuando empieza y ofrece corregirla cuando no est bien puesta. Esta configuracin es slo requerida para la funcin del API AccessibleObjectFromWindow y no se requiere para el Servidor en Produccin.
Figure 6: The Active Server pages Authentication settings.
El siguiente problema es algo que he sido incapaz de precisar la causa. No es un problema tan grave como la limitacin del entorno de desarrollo. El servidor COM usado bajo ASP debe ser compilado como un servidor fuera de proceso, un EXE, para permitir a la funcin del API del Active Accessibility trabajar. Cada vez que uso un in process server, ya sea un regular o un multi threaded DLL, la funcin AccessibleObjectFromWindow falla con un error E_FAIL. Este es un error muy genrico de COM y no ayuda a poder localizar el problema. Una vez que el proceso de depuracin se ha terminado el servidor COM se puede construir como un single o un multi threaded DLL segn lo que se requiera. Para hacer una prueba de depuracin, inicia Visual FoxPro7 en el directorio AspDebug. Primero necesitars ya sea hacer un BUILD EXE AspDebug FROM AspDebug para crear el servidor COM inicial o hacer un /regserver del actual AspDebug.exe usando el archivo register.bat. A continuacin, escribe DO MAIN en la ventana de instrucciones de Visual FoxPro y pulsa Enter. La primera vez que hagas esto vers un mensaje informandote de que el directorio virtual para este proyecto no se ha encontrado y preguntndote si quieres crearlo. Haz Click en el botn de OK para crear el nuevo directorio virtual de Internet Information Server. A continuacin aparecer el formulario de estado y se iniciar el browser por defecto. El browser automticamente navegar a la pgina por defecto de la web. Cuando vuelvas a Visual FoxPro vers la primera peticin ASP en el formulario de estado.
Listing 3: The code in the Active Server Pages default.asp. <% Dim oDemo Set oDemo = Server.CreateObject("AspDebug.AspDebug") Set oDemo = oDemo.GetDebugObject()
oDemo.Test() %> Para depurar el servidor marca el Debug checkbox, vuelvete al browsers y pulsa F5 para refrescar la pgina. Se abrir el depurador de Visual FoxPro y te dejar al final del mtodo OnStartRequest(). Usa F8 para avanzar paso a paso a travs del OnStartPage() y el mtodo OnStartAspRequest() hasta que te encuentres en el mtodo Test(). Este es el mtodo que se llama desde la pgina Default.asp para generar el output HTML. Nota que puedes hacer cualquier cosa que puedes hacer de forma normal cuando depuras una aplicacin normal de Visual FoxPro. Como puedes ver el Request ASP est disponible de la misma forma como lo estara en un servidor COM normal corriendo bajo ASP. Fjate en el cdigo del debugger cambiando una variable en el objeto Session de la ASP. Cambiar el cdigo es tan fcil como desarrollar una aplicacin normal. Haz click en el botn de cerrar, abre AspDebug.prg en el editor y cambia algo de cdigo en el mtodo Test(). Por ejemplo aade la siguiente lnea de cdigo al final del mtodo Test():
Guarda el programa y ejecuta el programa principal de nuevo sin construir un nuevo servidor COM. Deberas ahora ver el nuevo mensaje al final de la pgina. Como ayuda adicional, debido a que el depurador de Visual FoxPro no muestra todas las variables ASP que estn disponibles a travs de los objetos ASP, he aadido la opcin de descargar parte o toda la informacin de las ASP al final del mtodo response. Para mostrar esto establece la descarga de la ASP a basic o full y refresca la pgina.
Conclusin La solucin presentada genera un gran rendimiento en productividad a la hora de desarrollar COM en general y entornos ASP en particular. El desarrollo gana mucho en interactividad y las posibilidades de depuracin son una enorme beneficio.
Maurice de Beijer Copyright 2002 ABL - The Problem Solver. All rights reserved.