Comunicación Entre Ejecutables
Las Referencias a un Unico Objeto
Compartido es la
Técnica ActiveX de Alto Nivel para Comunicar Datos Entre
Ejecutables
Por Harvey Triana
Septiembre 12 de 2000
Una de las cuestiones por las que suelo
recibir preguntas es como transferir datos de un ejecutable a otro. La
respuesta es simpre la misma: crea un componente fuera de proceso. La
documentación de Visual Basic presenta el ejemplo conocido como la clase CoffeeMonitor.
No obstante este ejemplo, a parte de extenso, suele parecer complicado y la
forma de compartir datos entre diferentes clientes parece poco asible.
Desafortunadamente el ejemplo de la
MSDN termina la exposición con este titulo : "Un error
en la clase Connector", y termina con "...en las aplicaciones de
ejemplo Coffee2.Vbp y CoffWat2.Vbp se explora una posible solución a este
error"; supongo que algo así desanima a más de uno. El ejemplo que
presento en este articulo tiene dos propósitos: (1) Aislar el tratamiento de
las clases compartidas (para presentar su funcionalidad claramente), y (2)
Solventar el problema: "Un error en la clase Connector".
Este articulo supone que el lector tiene alguna experiencia en la creación de
componentes ActiveX.
Introducción
Recordemos que los componentes pueden ejecutarse en proceso o fuera de
proceso con respecto a los clientes que utilizan sus objetos. Un componente
fuera de proceso, o componente EXE ActiveX, se ejecuta en su propio espacio
de direcciones. En virtud de esto, un componente EXE ActiveX puede mantener
variables fuera del proceso del cliente. No obstante la implementasion de
variables compartidas sugiere una técnica para compartir un objeto para todos
los clientes.
Ejemplo Paso a Paso
El ejemplo que expondré a continuación muestra como la propiedad Message
de la clase CMessage se comparte entre diferentes ejecutables. Primero
crearemos el componente ActiveX Fuera de Proceso llamado Message.EXE.
Luego crearemos un cliente simple de Message.EXE llamado BinTest.EXE.
El Proyecto Message
1. En el menú Archivo, haga clic en Nuevo proyecto.
2. En el cuadro de diálogo Nuevo proyecto, haga doble clic en el icono EXE
ActiveX. Asigne Name=Message.
3. A la clase que fue creada como predeterminada daremos el nombre de
CMessage (Name=CMessage).
4. Implementamos la clase compartida CMessageStore. Esta clase usa una
referencia a un objeto global de un modulo estándar (Shared.BAS). Los
modulos estandar en Visual Basic se comportan similar a las clases estáticas
de Java, es decir, asi como declaramos Static en un procedimiento, las
variables se comparten a nivel de proyecto. La variable gCount
mantiene una cuenta lógica de las instancias de la clase CMessage, así
el sistema sabe cuando crear o destruir los recursos compartidos. Usamos WithEvents
para que podamos procesar eventos de un objeto creado en un modulo estándar
(debiera tomar esto como un "tip"). Cada cliente tiene un objeto CMessage,
y todos los cliente tienen un unico objeto de MessageStore. El código para
implementar un objeto compartido sule seguir este modelo:
Private WithEvents MessageStore As CMessageStore
Private Sub Class_Initialize()
If gCount = 0 Then
Set gMessageStore = New CMessageStore
End If
gCount = gCount + 1
Set MessageStore = gMessageStore
End Sub
Private Sub Class_Terminate()
If gCount - 1 = 0 Then
Set gMessageStore = Nothing
End If
gCount = gCount - 1
Set MessageStore = Nothing
End Sub
5. Creamos el evento MessageChange.
Este evento se crea con el propósito de notificar a los clientes que el
mensaje a cambiado, en otras palabras, que la propiedad Message ha
cambiado de valor. Por supuesto que una de las instancia es la que cambia el
mensaje, entones dispara el evento MessageChange en todos los demás
clientes activos.
Public
Event MessageChange()
...
Private Sub MessageStore_MessageChange()
RaiseEvent MessageChange
End Sub
6. Creamos la propiedad Message.
Esta propiedad representa una variable compartida. Note que quien almacena la
variable es la clase compartida CMessageStore, y CMessage.
Public
Property Get Message() As String
Message = MessageStore.Message
End Property
Public Property Let Message(RHS As String)
MessageStore.Message = RHS
End Property
7. Algun codigo de prueba. La propiedad
Count nos dira el numero de instancia de la clase CMessage
creada por los clientes.
'//Code
Test
Public Property Get Count() As Long
Count = gCount
End Property
8. En total, el código de la clase CMessage es el siguiente:
'------------------------------------------------
' NAME : CMessage
' TYPE : Class, Instancing=MultiUse
' PROJECT : Messages, EXE ActiveX
' AUTHOR : Harvey T.
' DESCRIPTION : Keeps shared class CMessageStore
' UPDATE : -
'------------------------------------------------
Option Explicit
Public Event MessageChange()
Private WithEvents MessageStore As CMessageStore
Private Sub Class_Initialize()
If gCount = 0 Then
Set gMessageStore = New CMessageStore
End If
gCount = gCount + 1
Set MessageStore = gMessageStore
End Sub
Private Sub Class_Terminate()
If gCount - 1 = 0 Then
Set gMessageStore = Nothing
End If
gCount = gCount - 1
Set MessageStore = Nothing
End Sub
Private Sub MessageStore_MessageChange()
RaiseEvent MessageChange
End Sub
Public Property Get Message() As String
Message = MessageStore.Message
End Property
Public Property Let Message(RHS As String)
MessageStore.Message = RHS
End Property
'//Code Test
Public Property Get Count() As Long
Count = gCount
End Property
9. El modulo Shared. Cree un
modulo estándar y de el valor Shared a la propiedad Name. El código de este
modulo es el siguiente:
'------------------------------------------------
' NAME : Shared
' TYPE : Standard Module
' PROJECT : Messages, EXE ActiveX
' AUTHOR : Harvey T.
' DESCRIPTION : Keeps shared data
' UPDATE : -
'------------------------------------------------
Option Explicit
Public gCount As Long
Public gMessageStore As CmessageStore
10. La clase CMessageStore. Esta es la
clase compartida, es quien realmente mantiene la variable compartida
(m_Message). El código es el siguiente:
'------------------------------------------------
' NAME : CMessageStore
' TYPE : Class, Instancing=Private
' PROJECT : Messages, EXE ActiveX
' AUTHOR : Harvey T.
' DESCRIPTION : This is the shared class
' UPDATE : -
'------------------------------------------------
Option Explicit
Public Event MessageChange()
Private m_Message As String
Public Property Get Message() As String
Message = m_Message
End Property
Public Property Let Message(RHS As String)
m_Message = RHS
RaiseEvent MessageChange
End Property
11. Por ultimo genere el ejecutable
Message.EXE.
El Proyecto de Prueba
1. En el menú Archivo, haga clic en Nuevo proyecto.
2. En el cuadro de diálogo Nuevo proyecto, haga doble clic en el icono EXE
Estándar. Daremos al proyecto el nombre de BinTest (Name= BinTest)
3. Al formulario predeterminado demos el nombre de frmBinTest.
4. Agreguemos un CommandButton (Name=cmdSend), un segundo CommandButton
(Name= cmdTestCount) y un TextBox (Name= txtMessage). La disposición de los
controles es la siguiente:

5. Agreguemos la referencia al componente Message
creado anteriormente: Desde el Menú Proyecto, Opción: Referencias. Ubique el
archivo Message.EXE (puede ser mas cómodo hacerlo desde el botón Examinar).
6.
Agregue el siguiente código al formulario frmBinTest:
'------------------------------------------------
' NAME : frmBinTest
' TYPE : Form
' PROJECT : BinTest, EXE Standard
' AUTHOR : Harvey T.
' DESCRIPTION : Sample of Shared Class
' UPDATE : -
'------------------------------------------------
Option Explicit
Private WithEvents msg As Messages.CMessage
Private Sub cmdSend_Click()
txtMessage.SetFocus
msg.Message = txtMessage.Text
End Sub
Private Sub cmdTestCount_Click()
txtMessage.Text = "Count = " & msg.Count
End Sub
Private Sub Form_Load()
Set msg = New Messages.CMessage
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set msg = Nothing
End Sub
Private Sub msg_MessageChange()
If Not txtMessage.Text = msg.Message Then
txtMessage.Text = msg.Message
End If
End Sub
7. Por ultimo genere el ejecutable BinTest.EXE.
Prueba
Abra el ejecutable BinTest.EXE las veces que desee. Ahora escriba algo
en la caja de texto y use el comando Send. Vera que todos los cliente
reconocen el mensaje. La siguiente imagen fue mi prueba:

Use el comando TestCount para
reflejar el numero de instancia de la clase CMessage (cierre y abra
nuevas instancias de BinTest.EXE para mas claridad).
Utilización en el Mundo Real
Por supuesto la aplicación BinTest no el único cliente que puede utilizar Message.EXE,
lo pueden utilizar en otros programas creados con Visual Basic, y en general
todo lo que siga la norma ActiveX, por ejemplo cualquier aplicación de
Office, programas creados con J++, etc.
Quizás los servicios de compartir variables entre ejecutables sea mas
interesante en un entorno de network o en el Web. Por supuesto aquí es donde
Ud. Debe crear un componente distribuido. El código no es diferente, el
despliegue en red si que lo es.
|