Compartir a través de


FoxIs, un servidor de Internet de Visual FoxPro

FoxIs, que se encuentra en el directorio …\Samples\Servers\Foxisapi\FoxIs de Visual FoxPro, ilustra la creación de un .exe fuera de proceso o de una .dll en proceso con funcionalidad ISAPI, lo que permite el acceso a él desde Visual FoxPro como programa independiente, desde clientes de Automatización o desde un explorador de Web. Los cambios que realice en sus clases pueden mejorar el servidor de Automatización, independientemente de cómo se ejecute.

Para abrir el proyecto de ejemplo FoxIs

  • Escriba la siguiente línea de código en la ventana Comandos:

    MODIFY PROJECT (HOME(2) + 'servers\foxisapi\foxis\foxis')
    

Ejecutar el ejemplo FoxIs

Puede ejecutar el ejemplo FoxIs de cuatro maneras distintas. Cuando esté probando el código, se recomienda que ejecute el ejemplo en el orden siguiente:

Ejecutar desde Visual FoxPro

Para ejecutar el ejemplo FoxIs desde Visual FoxPro, ejecute el siguiente código en la ventana Comandos.

SET DEFAULT TO (HOME(2) + 'servers\foxisapi\foxis\')
SET CLASSLIB TO employee
ox = CREATEOBJECT('employee')
ox.show

Ejecutar como un ejecutable independiente

Puede generar el ejemplo en un archivo ejecutable con la siguiente línea de código:

BUILD EXE foxis FROM foxis

El archivo compilado, FOXIS.EXE, es un programa de Windows que se puede agregar al menú Inicio de Windows o que se puede iniciar desde el Explorador de Windows, etc.

Ejecutar como servidor de Automatización

Una vez compilado el ejemplo FoxIs para crear un archivo .exe o .dll, se registra como un servidor de Automatización en el Registro de Windows. Puede crear un objeto basado en la clase Employee desde cualquier controlador de OLE, como Excel, Visual Basic y Visual FoxPro:

ox = CREATEOBJECT('foxis.employee')
ox.SHOW

Ejecutar desde un explorador de Web

Incluso puede ejecutar el ejemplo FoxIs desde un explorador de Web, que podría estar en otro equipo, por ejemplo un 286 que trabaje con MS-DOS, un equipo Unix, un Macintosh o un Personal Digital Assistant.

Requisitos del sistema para la utilización de Internet

Para ejecutar el ejemplo FoxIs desde un explorador de Web, es necesario que trabaje con:

  • Windows 98 o Windows NT 4.0 o posterior.
  • Un servidor de Web compatible con ISAPI, como Microsoft Personal Web Server para Windows 98 o Microsoft Internet Information Server (IIS). IIS está incluido con Windows NT 4.0 y posterior, y se puede descargar gratuitamente desde www.microsoft.com; Personal Web Server también se puede descargar desde www.microsoft.com.

Si está utilizando Windows NT 4.0 o posterior, debe ejecutar la aplicación DCOMCNFG para configurar DCOM de forma que conceda derechos al servicio IIS para crear instancias de objetos OLE.

Para configurar DCOM de Windows NT 4.0 o posterior

  1. En la línea de comandos, escriba DCOMCNFG y presione Entrar.

  2. En la ficha Aplicaciones, seleccione el nombre del servidor de Automatización. Cuando se genera el servidor, la aplicación predeterminada será "employee".

  3. En la ficha Seguridad predeterminada del cuadro de diálogo Propiedades de configuración de COM distribuido, elija Modificar valor predeterminado para cada área: Permisos de acceso predeterminados, Permisos de inicio predeterminados y Permisos de configuración predeterminados.

  4. En el cuadro de diálogo Registrar permisos de valores para cada área, elija Agregar.

  5. En el cuadro Agregar nombres del cuadro de diálogo Agregar usuarios y grupos, escriba el nombre de su servidor de WWW y su nombre de usuario para el inicio de sesión.

    Puede ver el nombre del servidor en la ventana de Propiedades de Microsoft Internet Service Manager. Si el nombre de su equipo es MINE, la siguiente línea en el cuadro Agregar nombres configura un usuario predeterminado:

    \MINE\IUSR_MINE
    

    Si el nombre de su equipo es MINE y su nombre de usuario es HOMER, la siguiente línea del cuadro Agregar nombres configura permisos para usted cuando inicia una sesión:

    \MINE\HOMER
    

Configurar el ejemplo FoxIs para el acceso a Internet

Para configurar el ejemplo FoxIs, debe crear un archivo .exe o .dll desde el proyecto FoxIs y, luego, copiarlo al directorio Inetsvr\Scripts.

Para configurar el ejemplo FoxIs

  1. Abra el proyecto FOXIS.
  2. Elija el botón Generar y, después, Generar DLL COM.
  3. Copie Foxisapi.dll a la carpeta Inetsrv\Scripts.

Pruebas preliminares

Puede probar la aplicación de ejemplo FoxIs a varios niveles para ver si está correctamente configurada.

Para ver si funciona el código

  1. En el menú Programa elija Ejecutar.
  2. Seleccione Main.prg en la carpeta Samples\Servers\Foxisapi de Visual FoxPro.
  3. Elija Ejecutar.

Para ver si funciona el archivo .EXE

  1. En la ventana Comandos de Visual FoxPro, ejecute el comando siguiente:

    BUILD EXE Foxis.exe FROM foxis
    
  2. Haga doble clic en Foxis.exe en el Explorador de Windows.

Para ver si funciona el servidor de Automatización FoxIs

  • Ejecute los siguientes comandos:

    OX= CREATEOBJECT('FOXIS.EMPLOYEE')
    OX.Show    && See if it works as a ISAPI Automation server
    ?OX.Startup( )  && See if it returns html
    

Es mucho más fácil depurar servidores de Automatización desde un controlador de Automatización (como Visual FoxPro) que crear una instancia en FoxIs.

Instalar la página HTML

Para empezar a trabajar, necesita una página HTML que contenga una referencia a una dirección URL. Por ejemplo, ponga el siguiente código en el archivo Wwwroot\default.htm.

<a HREF="/scripts/foxisapi.dll/FoxIS.employee.startup"> <i>VFP ISAPI AUTOMATION SERVER DEMO PAGE</i> </a> 

Después utilice un explorador (que puede estar en el mismo equipo) y conéctese a YourMachineName. Por ejemplo, si su equipo se llama "myMachine", escriba "myMachine" como la dirección URL a la que desea dirigirse. Esto hará que la página Default.htm aparezca en el servidor con el nombre "myMachine".

Se ha iniciado un método CreateObject("foxis.employee") y se ha invocado el método Startup en el objeto, que devuelve una página HTML generada. Si todavía no se ha generado el servidor de Automatización ISAPI, Foxisapi.dll devolverá una página de error de HTML.

Después utilice su explorador de Web para el acceso a la anterior referencia de controlador (href). Si recibe una página HTML de error que indica un "Error de Foxisapi", significa que la DLL se está cargando y está trabajando.

 <FORM ACTION = "/scripts/foxisapi.dll/foxis.employee.cmd">
<INPUT NAME="Cmd" VALUE = "Reset">
<INPUT TYPE="submit" VALUE="Dos Command">
</FORM>

Además, puede colocar cualquier comando de MS-DOS válido y se ejecutará en el equipo servidor. Si el comando es "Reset" (predeterminado), hará que el servidor de Automatización ISAPI libere la primera instancia así como la suya propia, con lo que se liberará completamente el servidor de Automatización ISAPI.

También puede evaluar cualquier expresión de Visual FoxPro. De todas formas, si la expresión de Visual FoxPro muestra una interfaz modal, como hace la función MESSAGEBOX( ), el servidor de Automatización se bloqueará en espera de una respuesta que no se puede obtener. Sin embargo, en el caso de una .dll en proceso, la interfaz modal se administra automáticamente y el servidor de Automatización no se bloquea.

<FORM ACTION = "/scripts/foxisapi.dll/foxis.employee.cmd?FOXCMD">
<INPUT NAME="Cmd">
<INPUT TYPE="submit" VALUE="Fox Expression">
like "today is "+ cdow(date()) or 45 * 3 or SYS(2004)
</FORM>

Depurar el servidor

Un servicio de Windows NT carece de escritorio, por consiguiente no aparecerá ninguna interfaz de usuario en el servidor. Esto quiere decir que usted debería depurar las aplicaciones de su servidor antes de distribuirlas.

Para realizar un seguimiento de Foxisapi.dll con Visual C++ 5.0

  1. Abra Foxisapi.mak.

  2. Quite la marca de comentario de la siguiente línea en HttpExtensionProc:

    //   _asm int 3
    
  3. Vuelva a generar el proyecto.

  4. Inicie MSDEV con el Id. de proceso (PID) de Inetinfo.exe. Puede obtener el Id. de proceso en el Administrador de tareas de Windows.

Este proceso se aplica a Windows NT 4.0 o posterior.

**Sugerencia   **Durante la depuración, no es necesario que cierre el servidor Web para cambiar el servidor de Automatización. Puede, simplemente, terminar el componente fuera de proceso al enviar un valor de reinicio al método cmd, como se describió anteriormente, o al utilizar las herramientas SDK TLIST, KILL, PVIEW de Win32 o el Administrador de tareas en Windows NT 4.0 o posterior.

La clase ISForm

El "motor" del ejemplo es la clase ISForm en Isapi.vcx.

Punto de entrada a la clase ISForm

Se puede llamar a los siguientes métodos desde el explorador de Web, mediante Foxisapi.dll, para devolver páginas HTML.

Método Devuelve
Cmd Evaluación de una expresión de Visual FoxPro o el resultado de un comando de MS-DOS.
DoSave Guarda los cambios realizados en los datos por el usuario y devuelve la página HTML del empleado.
Skipit La información del empleado especificado en la tabla. Skipit toma información de cookies pasada como un parámetro desde el explorador de Web, examina la tabla de cookies en busca del número del registro anterior y desplaza el puntero del registro hacia delante o hacia atrás respecto al número de registro almacenado en la tabla de cookies. Se vuelve a escribir el número del registro nuevo en la tabla de cookies y se llama al método GenHTML.
Startup La información acerca del primer empleado de la tabla. Startup crea un nuevo Id. de cookie para el usuario y vuelve a enviarlo en forma de un área de entrada oculta en la página HTML.

Mantener activo el servidor

Generalmente, para cada petición de un cliente de Web, se crea una instancia del servidor de Automatización, se genera una página HTML y se libera con la llamada Release( ) en CallObject( ) de Foxisapi.cpp. Esto quiere decir que el tiempo de ejecución de Visual FoxPro se iniciará y cerrará por completo para cada petición.

Si el servidor de Automatización ISAPI está registrado como Uso múltiple y no se llama a Release( ), la primera petición iniciará el servidor, pero las siguientes peticiones utilizarán la misma instancia del servidor, lo que mejorará considerablemente el rendimiento. El código de Foxisapi.dll y de los métodos Load, Cmd, DoSave, Startup y Skipit de ISForm controlarán el mantenimiento de la misma instancia del servidor activo.

Variables de la DLL

Hay dos variables declaradas: pdispObj y pdispDoRelease. En la creación del servidor, pdispObj es el controlador de ejecución del objeto OLE. La variable pdispDoRelease se establece con el mismo valor que pdispObj y se pasa por referencia como un parámetro al método del servidor ISForm solicitado por el explorador de Web. El código del servidor de Automatización ISForm de Visual FoxPro puede cambiar el valor de pdispDoRelease.

**Sugerencia   **Si desea más información acerca de este ejemplo, vea los comentarios en el código de ISForm y Foxisapi.cpp.

El evento Load del formulario

Cuando se crea ISForm, el código del evento Load crea dos variables públicas, gpInstance y gpDisp. La primera vez que se carga el servidor ISForm, la variable gpInstance se establece como 1. Las instancias subsiguientes aumentarán esta variable. Cuando se libera una instancia, disminuye el valor de gpInstance.

Los métodos de punto de entrada

Cuando se invoca un método (Cmd, DoSave, Skipit o Startup) de ISForm a través de Foxisapi.dll, la DLL pasa un puntero de ejecución por referencia como un parámetro para el método.

La primera vez que se ejecuta el servidor, el contador de instancias se establece en 1 y el puntero de ejecución se almacena en la variable global. A continuación se almacena el valor 0 en el puntero de ejecución.

IF m.gnInstance = 1 
   IF TYPE('pDisp') $ 'NI' 
      gpDisp = m.pDisp
      pDisp = 0
   ENDIF
ENDIF

En este momento hay dos variables que señalan al mismo valor de puntero de ejecución: gpDisp del servidor de Automatización ISForm y pdispObj de Foxisapi.dll. El valor de pdispDoRelease en la DLL es 0, pues se ha modificado en el servidor de Automatización ISForm.

Las próximas veces que se llame al servidor, aumentará el contador de instancias, se generará un nuevo pdispObj en la DLL, almacenado en pdispDoRelease, y se pasará por referencia al método solicitado. Dado que el valor de gnInstance es distinto de 1, no se modifica la variable gpDisp. A partir de este punto, gpDisp en el servidor de Automatización tendrá un valor distinto que el de pdispObj y pdispDoRelease en la DLL.

El código de la DLL

El siguiente código de C++ de Foxisapi.cpp administra la liberación del servidor. Una vez creada la primera instancia, las siguientes instancias se liberarán generalmente con la llamada Release( ) en CallObject( ) de Foxisapi.cpp porque pdispObj y pdispDoRelease están establecidas con el mismo valor distinto de cero.

if (pdispDoRelease != 0) {
   pdispObj->Release();  //nonzero, so release the current object
   if (pdispObj != pdispDoRelease) {
      __try {   
         (pdispDoRelease)->Release();
      } __except  (EXCEPTION_EXECUTE_HANDLER) {

      }
   }
}

El evento Destroy del ISForm disminuye el contador de instancias. En el caso de que sólo haya una instancia, pdispDoRelease se ha establecido en 0 y no se llamará al código de liberación. Si pdispObject y pdispDoRelease son la misma, se liberarán las instancias subsiguientes, pero no así la instancia original.

Liberar el servidor

Para forzar una liberación, pdispDoRelease tiene que ser distinta de 0 y debe tener un valor diferente que el de pdispObject. El siguiente texto HTML envía un valor al servidor que afecta a la liberación:

 <FORM ACTION = "/scripts/foxisapi.dll/foxis.employee.cmd">
<INPUT NAME="Cmd" VALUE = "Reset">
<INPUT TYPE="submit" VALUE="Dos Command">
</FORM>

El siguiente código del método cmd establece el valor de pdispDoRelease como el valor de ejecución de la primera instancia.

CASE 'RESET'$upper(m.p1)
   m.pDisp= m.gpDisp

El código de la DLL ahora liberará la instancia actual y la instancia original que se ha mantenido existente para impedir que el tiempo de ejecución de Visual FoxPro tuviera que volverse a cargar cada vez que se llamara al servidor.

Enviar HTML de vuelta al cliente

Se llama al método GenHTML de la clase ISForm desde cada método de punto de entrada. La página HTML devuelta desde el método GenHTML se devuelve al explorador de Web a través del Internet Information Server.

Si el parámetro de modo que se ha pasado al método GenHTML no es "FORM", el método GenHTML simplemente buscará en una tabla y mandará la página HTML antes de que reciba formato.

IF m.mode != 'FORM'
   =SEEK(m.mode,'html')
   rv = html.html
  RETURN m.rv
ENDIF

Si el parámetro de modo es "FORM", el código en GenHTML identificará cada una de las etiquetas y cuadros de texto del formulario, los ordenará de izquierda a derecha y de arriba a abajo, evaluará las propiedades Caption y ControlSource de los controles y utilizará la capacidad de mostrar texto de Visual FoxPro para construir el texto de HTML adecuado para aproximar la presentación del formulario.

Si agrega etiquetas y cuadros de texto adicionales al formulario, se mostrarán automáticamente en el código HTML generado.

Crear y utilizar cookies

Como servidor de Web, muchos clientes pueden tener acceso a esta aplicación muchas veces y necesitamos realizar un seguimiento del estado del usuario. En este caso, sólo realizamos un seguimiento del número del registro actual para dicho usuario. Podríamos presentar al usuario una pantalla de inicio de sesión y utilizar el nombre de usuario como una clave para el cookie, pero en lugar de eso, generamos un valor de cookie en el método MakeCookie y lo pasamos como un valor oculto del código HTML que se devuelve al usuario. Cada vez que el usuario escoge ir a un registro distinto, podemos leer el valor del cookie desde la cadena de HTTP enviada a la DLL, localizar el cookie en la tabla Cookies, encontrar el número de registro actual y desplazar el número de registro correspondiente a este número.

En el proceso de manipulación de cookies se utilizan la siguiente propiedad y los siguientes métodos:

  • Propiedad Cookie
  • Método GetCookie
  • Método MakeCookie
  • Método WriteCookieInfo

Tratamiento de errores

Si se produce un error, el código del evento Error de la clase ISForm llama al método GenHTML con un parámetro "ERROR". GenHTML lee el texto de HTML, aún sin formato, en busca de errores y lo devuelve al código del evento Error. El código del evento Error substituye la información de error para marcadores de posición en el código HTML:

   LOCAL rv
   rv = THIS.GenHTML('ERROR')
   rv = strtran(m.rv,'%METHOD%',m.cMethod)
   rv = strtran(m.rv,'%ERRORNO%',STR(m.nError,4))
   rv = strtran(m.rv,'%ERRORMSG%',Message(1))
   rv = strtran(m.rv,'%LINENO%',STR(m.nLine,4))
   THIS.ErrorHTML = m.rv

Cuando la propiedad ErrorHTML no está vacía, GenHTML envía el valor de ErrorHTML al cliente.

Tablas utilizadas en el ejemplo FoxIs

Además de la tabla de empleados utilizada para la entrada y la presentación de datos, el ejemplo FoxIs utiliza las siguientes tablas.

Tabla Descripción
HTML Contiene el texto HTML que se va a enviar al explorador de Web como un encabezado para las evaluaciones de FoxCMD y DosCMD o en caso de que se produzca un error.
Cookies Realiza un seguimiento de números de registro para distintos exploradores de Web. El valor de campo de cookie único se pasa como un valor oculto en el texto HTML enviado a un usuario específico.

Vea también

Ejemplos de soluciones | Ejemplos de servidor de Automatización FoxISAPI | FoxWeb, un servidor de Automatización de Visual FoxPro para Internet simplificado