You are on page 1of 10

FoxPress Enero 2003

Desarrollo y Depuracin de Servidores COM con


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():

This.oResponse.Write('<p>Hi there: ')
This.oResponse.Write(This.oRequest.ServerVariables('auth_user'))

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.

FoxPress Enero de 2003

You might also like