Por Paco Simarro. psimarro@interbook.net ActiveX (21 K)
Cuantas veces nos ha ocurrido que en el momento de instalar nuestro nuevo programa en casa del cliente, o en un nuevo puesto de la red y nos disponernos a mostrarles las maravillas que le hemos preparado, entre las que hemos introducido algún que otro control ActiveX, a la hora de ejecutar el programa nos salta el tan indeseado error que se reproduce a continuación:
¿Cómo se soluciona esta situación?. Pués es bién sencillo, y la mayoría de los lectores ya conocen la solución, copiando nuestro archivo OCX sobre el directorio de Windows y después ejecutando:
REGSVR32 C:\WINDOWS\SYSTEM32\MIARCHIVO.OCX
Con lo cual el control quedará debidamente registrado y listo para ser empleado por nuestro programa. Pero la sensación inicial que sufre el usuario ante la circunstancia descrita es la de que somos un poco chapuceros.
Después de que esta situación se me repitiera con cierta frecuencia, debido al despiste que me acompaña desde que ví la luz del día por primera vez, me planteé la posibilidad de investigar si sería posible preparar alguna utilidad que me evitara estas situaciones tan sonrojantes. Y después de un tiempo y de encontrar en la red de redes las utilidades que necesitaba para ello, me dispuse a integrar esta utilidad en mi programa encargado de lanzar la aplicación.
La utilidad consiste en guardar en una tabla la información de los controles ActiveX que utilizo habitualmente. Y cada vez que arranco el programa recorro la tabla y compruebo si cada uno de los controles está registrado. Y si no es así, pues lo copio al directorio del sistema y después lo registro. De esta forma, me olvido también de incluir en la instalación los componenetes ActiveX, y marcarlos como tales en el proceso de generación de los discos de instalación. Paso a explicar más detalladamente esta cuestión.
En primer lugar en el directorio de mi aplicación tengo un subdirectorio llamado ActiveX, dentro del cual he creado una tabla llamada igualmente ActiveX, con la siguiente estructura:
· cFileOCX c(25)
· cOleClass c(40)
En el primer campo guardo el nombre del archivo OCX que contiene los controles (Ej. El COMCTL32.OCX), y en el segundo guardo el OleClass, de uno de los controles contenidos en el archivo OCX. El segundo valor podemos verlo si insertamos un control en un formulario, seleccionamos la ventana de propiedades y vemos el valor de la propiedad OleClass (Ej. El caso del treeview: COMCTL.TreeCtrl.1).
En el mismo directorio guardo igualmente los archivos OCX que se corresponden con los registros de la tabla mencionada, para copiarlos y registrarlos si el cliente no los tiene aún.
El siguiente problema que me encontré era el de cómo comprobar si un control activex estaba o no registrado en el ordenador, y después de bucear durante un buen rato en el registro de Windows me dí cuenta de que por cada control había una entrada con la clave del OleClass en la clave primaria HKEY_CLASSES_ROOT. No tenía más que buscar esa clave en el registro y si no la encontraba es que el control no estaba debidamente registrado.
Para trabajar con el registro he usado la clase Registry de Rick Strahl, que es fantástica, y además de dominio público. Me vino de perlas para comprobar si existía la entrada mencionada en el registro. Podeis encontrar esto en registry.prg.
Después necesitaba registrar el control y siempre pensé que ejecutar con un RUN el REGSVR32 desde mi programa no era muy elegante. Investigando un poco encontré también un par de funciones de Paul Vlad Tatavu, que me vinieron de perlas. Resulta que cada archivo OCX contiene en sí mismo un par de funciones para registrarse y desregistrarse (DllRegisterServer y DllUnregisterServer), no hay mas que declararlas y utilizarlas para registrar/desregistrar el control. Incluí esas dos funciones como métodos de la clase Registry, aunque la única que se utiliza en el código es RegisterControl.
También utilizo la función oPrg_Disk_CopiaFile, que es una función mía que utilizo para copiar archivos, y la función oPrg_Disk_SystemDir, que es de Luis María Guayan aunque un poco retocada, y la utilizo para localizar el directorio del sistema de Windows, todo ello va incluido en el archivo utilidad.prg.
No queda más que exponer el código que utilizo para recorrer la tabla ActiveX y demás operaciones descritas, que se encuentra en el archivo ActiveX.prg:
* Ahora vamos con la comprobación de la instalación de los
controles ActiveX
PUBLIC cRutaServ, oRegistry
LOCAL cValorRegistro, laOCXLocal, laOCXServer, cFileLocal,
cFileServ
CRutaServ = ‘C:\MIAPP\’
oRegistry=CREATE("Registry")
IF FILE(cRutaServ+'ACTIVEX\ACTIVEX.DBF')
* Está la tabla de los
ActiveX a utilizar
USE
(cRutaServ+'ACTIVEX\ACTIVEX.DBF') ALIAS CX
GO TOP
SCAN
cValorRegistro =
ALLTRIM(oRegistry.ReadRegistryString(HKEY_CLASSES_ROOT,;
ALLTRIM(Cx.cOleClass),;
""))
IF
!ISNULL(cValorRegistro)
* El control está
registrado
* Puede darse la
circunstancia, de que a pesar de estar registrado el control, el
* archivo OCX haya
sido eliminado del directorio del sistema de Windows.
* Lo comprobamos por
si acaso.
cFileServ =
cRutaServ+'ACTIVEX\'+CX.cFileOCX
cFileLocal
= oPrg_Disk_SystemDir()+CX.cFileOCX
IF !FILE(cFileLocal)
IF
oPrg_Disk_CopiaFile(cFileServ,cFileLocal,llMuestraMensajeCopiado)
IF
oRegistry.RegisterControl(cFileLocal)
WAIT WIND 'Registrado control
'+CX.cFileOCX NOWAIT
ELSE
WAIT WIND 'ATENCION:'+CHR(13)+'No se ha podido
registrar el control '+CX.cFileOCX
ENDIF
ENDIF
ELSE
*
El archivo OCX está en su sitio.
* Y todo está OK.
ENDIF
ELSE
* El control no está registrado
cFileServ =
cRutaServ+'ACTIVEX\'+CX.cFileOCX
cFileLocal = oPrg_Disk_SystemDir()+CX.cFileOCX
IF !FILE(cFileLocal)
IF
oPrg_Disk_CopiaFile(cFileServ,cFileLocal,llMuestraMensajeCopiado)
IF oRegistry.RegisterControl(cFileLocal)
WAIT WIND 'Registrado control
'+CX.cFileOCX NOWAIT
ELSE
WAIT WIND 'ATENCION:'+CHR(13)+'No se ha
podido registrar el control '+CX.cFileOCX
ENDIF
ENDIF
ELSE
* El OCX ya se encuentra en el directorio del sistema local
* Podría darse el caso de que se tratara de
una versión distinta de la
* que vamos a utilizar.
IF ADIR(laOCXLocal,cFileLocal) = 1 AND
ADIR(laOCXServer,cFileServ) = 1
IF laOCXLocal[1,3] # laOCXServer[1,3]
IF
oPrg_Disk_CopiaFile(cFileServ,cFileLocal,llMuestraMensajeCopiado)
ENDIF
ELSE
ENDIF
ELSE
ENDIF
*-
IF oRegistry.RegisterControl(cFileLocal)
WAIT WIND 'Registrado control
'+CX.cFileOCX NOWAIT
ELSE
WAIT WIND 'ATENCION:'+CHR(13)+'No se ha
podido registrar el control '+CX.cFileOCX
ENDIF
*-
ENDIF
ENDIF
ENDSCAN
ENDIF
Para probarlo no teneis mas que introducir el valor correcto a la variable cRutaServ, y ejecutar el activex.prg.
En los ficheros del més os adjunto el resto del código necesario y espero que os resulte de utilidad lo que aquí os he expuesto.
FoxPress – Octubre de 2000
© 2000 FoxPress. All rights reserved