Llamadas telef贸nicas desde VFP

llynelli
05 de Enero del 2004
Como puedo efectuar llamadas telef贸nicas desde VFP y registrar llamadas entrantes???

Alguien tiene alg煤n ejemplo??

Mario
05 de Enero del 2004
DECLARE LONG tapiRequestMakeCall IN "TAPI32.DLL";
STRING DestAddress,;
STRING AppName,;
STRING CalledParty,;
STRING COMMENT

Numero = "475-730"
NombreProg = "c:/windows/dialer.exe"
Quien = "Orlando"
ValDev = tapiRequestMakeCall(Numero, NombreProg, Quien ,"hola ?")

Este es un ejemplo sacado de Portal Fox hecho por Jorge Mota

Saludos

Gustavo
05 de Enero del 2004
Te mando una nota de la revista foxpres, espero que te sirva, salludos


Visual FoxPro como cliente en Internet (I): Dial-Up Networking
Por Pablo Almunia
© Copyrights 1997 by FoxPress, All rights reserved
FoxPress, Junio 1997

Introducci贸n
Con este art铆culo empezamos una serie sobre c贸mo Visual FoxPro puede ser un cliente de los distintos servicios de Internet e intentaremos mostrar c贸mo podemos contruir una aplicaci贸n elegantemente integrada con la red de redes. En los pr贸ximos art铆culos veremos como recibir o enviar ficheros por FTP, como manejar los visualizadores HTML o como comunicar dos aplicaciones por medio de Internet.

Para empezar nos centraremos en como podemos arrancar y manejar un acceso a Internet desde Visual FoxPro, es decir, como podemos arrancar un Dial-Up Networking (Acceso Telef贸nico a Redes) de Windows 95 y Windows NT para comunicarnos con un proveedor de acceso a Internet.

Una aplicaci贸n elegante no presupone que existe una conexi贸n permantente con Internet y pregunta amablemente, si es necesario, qu茅 configuraci贸n de conexi贸n a Internet puede utilizar y si puede abrir una conexi贸n con ella. No existe peor aplicaci贸n que la que hace que tu modem se dispare a llamar sin saber qu茅 est谩 pasando.

¿C贸mo acceder a Internet?
Para acceder desde un puesto Windows 95 o Windows NT a Internet tenemos dos opciones diferentes: acceder directamente desde el puesto por medio de un Dial-Up Networking y un modem o tarjeta RDSI o acceder por medio de la red local y un Router o un Proxy que se conecta a la Internet.

Cuando un Proxy o un Router conectado a nuestra red local detecta que existe un paquete TCP/IP dirigido a una red diferente a la red local encamina ese paquete a la Internet. La conexi贸n del Proxy o Router a Internet puede ser permanente, pero tambi茅n puede hacer uso de un sistema de Dial-Up por lo que se realizar谩 una conexi贸n con un proveedor de acceso cuando se realice una petici贸n y desconectar谩 cuando se produzca un determinado tiempo de inactividad.

En caso de tener nuestro puesto configurado para realizar el acceso por medio de un Proxy o Router nuestra aplicaci贸n Visual FoxPro s贸lo tendr谩 que hacer uso de un protocolo Internet como FTP o HTTP configurado para hacer uso del Proxy o Router y los paquetes TCP/IP ser谩n encaminados a la Internet de forma trasparente para nuestra aplicaci贸n.

Si por el contrario el acceso a Internet se realiza directamente con Dial-Up Networking desde el puesto Windows 95 o Windows NT por medio de un modem o una tarjeta RDSI, la aplicaci贸n requiere que esa conexi贸n se realice antes que sea posible utilizar un servicio por medio de Internet.

Esta conexi贸n con Internet puede establecerla manualmente el usuario, o establecerse autom谩ticamente cuando realizamos una petici贸n TCP/IP a una red externa, pero en mi opini贸n es m谩s elegante que la aplicaci贸n realice la conexi贸n por si misma, si as铆 lo configura el usuario.

Por otra parte, el sistema de Dial-Up Networking, que aqu铆 vamos a describir, no s贸lo se utiliza para realizar una conexi贸n a Internet. Con este mecanismo podemos conectarnos a otros ordenadores o a otras redes que dispongan de un servidor de Remote Access Service (RAS). Cualquier puesto Windows 95 o Windows NT puede ser un servidor de RAS si dispone de un modem o tarjeta RDSI y nosotros configuramos el servicio, siendo una buena soluci贸n para conectarnos a la red de la oficina desde casa.

Veremos c贸mo se puede manejar el Dial-Up Networking desde Visual FoxPro, ya sea para conectarse a Internet como para conectarse a un puesto o red remota, pero no vamos a explicar como configurar estos servicios. Le recomendamos se dirija a la Knowledge Base de Microsoft donde existen excelente art铆culos sobre la configuraci贸n de Proxys, Routers y Dial-Up Networking.

Arrancar el Dial-Up Networking
La primera aproximaci贸n al manejo del Dial-Up Networking es muy simple: arrancar una conexi贸n del Dial-Up Networking por medio de ordenes del sistema operativo.

En Windows 95 y Windows NT utilizaremos t茅cnicas distintas, estos dos sistemas se diferencia bastante en el uso de los del Dial-Up Networking y deberemos ver cada caso por separado.

Para saber en qu茅 sistema operativo nos encontramos podemos hacer uso de la orden OS() de Visual FoxPro.

Windows 95
Si utilizamos Windows 95 podemos utilizar un programa del sistema llamado RunDLL32 que permite hacer una llamada a una funci贸n de una DLL. Con este programa llamaremos a la funci贸n RnaDial de la librer铆a Rnaui.dll pasando como par谩metro el nombre de la conexi贸n del Dial-Up Networing que hayamos configurado con anterioridad.

En Visual FoxPro escribir铆amos algo parecido a esto:

RUN /N Rundll Rnaui.dll,RnaDial Conexion1
En este caso estamos llamando a una conexi贸n llamada Conexion1. Debemos escribir el nombre de la funci贸n exactamente igual, con may煤sculas y min煤sculas para que funcione correctamente.

Windows NT
Si utilizamos Windows NT el sistema es muy similar, pero en este caso llamaremos a un programa del sistema directamente, este programa se llama RASDIAL.EXE. Le pasaremos como par谩metro el nombre de la conexi贸n del Dial-Networing que hayamos configurado con anterioridad.

En Visual FoxPro escribir铆amos algo parecido a esto:

RUN /N RASDIAL conexion1
Esta orden permite pasar tambi茅n como par谩metros el nombre del usuario y la password y de esta forma evitar tener que guardarlos en la configuraci贸n de la conexi贸n.

Evitar que salga el cuadro de di谩logo
Cuando llamamos por cualquiera de los medios anteriores aparece un cuadro de di谩logo con los datos de la configuraci贸n y preguntando si queremos conectar. Para evitar que aparezca ese cuadro de di谩logo debemos configurar el Dial-Up Networking.

En Windows NT simplemente debemos guardar la password de la conexi贸n y de esta forma no nos aparecer谩 ning煤n cuadro de di谩logo.

En Windows 95 es un poco m谩s complicado, pero tambi茅n es posible. Debemos instalar un versi贸n m谩s moderna del Dial-Up Networking de la que trae por defecto el sistema. Para ello podemos obtener el fichero MSISDN11.EXE del Web de Microsoft que trae el soporte para tarjetas RDSI y la versi贸n actualizada del Dial-Up Networking (no es necesario tener una tarjeta RDSI para instalar este complemento).

Una vez instalada la nueva versi贸n del Dial-Up Networking podemos ir a la opci贸n settings del mismo e indicar que no aparezca el cuadro de di谩logo anterior y posterior a la conexi贸n:





Si nuestra conexi贸n requiere usuario y password debemos realizar, de forma similar a Windows NT, una conexi贸n donde guardemos esa configuraci贸n:




El API del RAS
Con el sistema anterior tenemos muchas limitaciones: no podemos saber si ha funcionado correctamente la conexi贸n, no podemos mostrar las distintas configuraciones en un cuadro de dialogo creado por nosotros para que el usuario pueda elegir cual utilizar, no podemos colgar la llamada, etc. Para realizar este tipo de operaciones debemos hacer uso del API del Remote Access Service (RAS).

Todos los ejemplos los hemos construido para Windows 95 y Windows NT 4. El API de RAS est谩 disponible para Windows NT 3.51 y para Windows 3.x, pero las funciones, par谩metros y estructuras cambian en algunas ocasiones y ser铆a necesaria una adaptaci贸n de los ejemplos que aqu铆 vamos a mostrar.

Obtener las entradas en la configuraci贸n del Dial-Up Networking
En primer lugar vamos a ver como podemos obtener una lista con todas las configuraciones del Dial-Up Networking configurados para este equipo. Para ello vamos a utilizar la siguiente funci贸n:

DECLARE INTEGER RasEnumEntries ;
IN RASAPI32.DLL ;
INTEGER reserved,;
STRING PhoneBox,;
STRING @ RasEntryName,;
INTEGER @ SizeOfRasEntryName,;
INTEGER @ Entries
Esta funci贸n tiene un primer parametro reservado, en el que pondremos un 0. Luego necesita una cadena con la direcci贸n del phonebook. Windows NT 4 dispone de la posibilidad de tener varios un phonebook con posibles conexiones, Windows 95 guarda todas las conexiones en el Registry. Si estamos en Windows 95 o queremos utilizar el phonebook por defecto del sistema utilizaremos una cadena vacia.

Luego necesita una matriz de estructuras de tipo RASENTRYNAME. En este punto tenemos algunas dificultades desde Visual FoxPro, pues no es capaz de generar tipos de datos en forma de estructura y debemos utilizar un buffer del suficiente tama帽o como para contener la estructura y luego obtener cada uno de los elementos por su posici贸n dentro de este buffer.

Por 煤ltimo es necesario pasar el tama帽o total de la matriz de estructuras y una variable donde almacenar谩 el n煤mero de entradas del phonebook que se han incluido dentro de la matriz de estructuras.

Como ejemplo hemos incluido esta funci贸n dentro de un programa que requiere una cadena con el nombre de una matriz donde se almacenar谩n las entradas que se encuentren en la configuraci贸n del Dial-Up Networking.

******************************************
***
*** Construye una matriz con todas las
*** entradas del phonebook
***
******************************************
LPARAMETER cArrayReturn

LOCAL cStructRasEntryName
LOCAL cStructRasEntryNames, nSize
LOCAL nEntries, nResult, cRasEntryName

*** Definici贸n de la constantes necesarias
#DEFINE RAS_MAXENTRYNAME 256

*** Declaraci贸n de las funciones del API
DECLARE INTEGER RasEnumEntries ;
IN RASAPI32.DLL ;
INTEGER reserved,;
STRING PhoneBox,;
STRING @ RasEntryName,;
INTEGER @ SizeOfRasEntryName,;
INTEGER @ Entries

*** Creaci贸n de una estructura tipo
*** RASENTRYNAME
cStructRasEntryName = wordtoc(264) ;
+ REPLICATE( CHR(0), RAS_MAXENTRYNAME )

*** Creaci贸n de una matriz con esa
*** estructura
cArrayRasEntryNames = REPLICATE( ;
cStructRasEntryName, 255 )

*** Variable con el tama帽o de la matriz
nSize = LEN( cArrayRasEntryNames )

*** Variable en la que se retorna el n煤mero
*** de entradas encontradas
nEntries = 0

*** Llamada a la funci贸n para obtener la
*** informaci贸n
nResult = RasEnumEntries( 0, "", ;
@cArrayRasEntryNames, ;
@nSize, ;
@nEntries )

*** Dimensi贸n de la matriz como p煤blica
PUBLIC ARRAY &cArrayReturn.[nEntries]

*** Extracci贸n de los datos desde la matriz
*** de estructuras
FOR nCont = 0 TO nEntries - 1

*** Obtener una Estructura
cRasEntryName = SUBSTR( ;
cArrayRasEntryNames, ;
264*nCont + 1, 264 )

*** Asignar el nombre a la matriz
&cArrayReturn.[nCont+1] = SUBSTR( ;
cRasEntryName, 5, ;
AT(CHR(0),SUBSTR(cRasEntryName,5))-1)

NEXT

*** Retorno del n煤mero de elementos que han
*** encontrado
RETURN nEntries
Gracias a este programas podemos ya mostrar todas las posibles configuraciones de conexi贸n antes de llamar a la misma, permitiendo que el usuario seleccione cual debemos utilizar.

Realizar una llamada por RAS
Para realizar una llamada directamente desde un programa Visual FoxPro, y no por medio de llamadas a ordenes del sistema operativo, debemos hacer uso principalmente de la funci贸n siguiente:

DECLARE Integer RasDial ;
IN RASAPI32.DLL ;
Integer RasDialExtensions, ;
Integer Phonebook, ;
String @ RasDialParams, ;
Integer NotifierType, ;
Integer Notifier, ;
Integer @ hRasConn
Esta funci贸n utiliza como primer par谩metro una estructura tipo RASDIALEXTENSIONS con informaci贸n extra que s贸lo es utilizada desde Windows NT. Como nosotros no vamos a pasar esa estructura hemos definido el dato como Integer y no como String y de esta forma pasar un 0 como valor. Su segundo par谩metro es un puntero a una cadena con la ruta de un phonebook de Windows NT. Como nosotros vamos ha utilizar el phonebook por defecto o las entradas en el registro de Windows 95 lo hemos definido de tipo Integer y pasaremos un 0.

El siguiente par谩metro es muy importante, es una estructura RASDIALPARAMS con los parametros de la conexi贸n que queremos realizar. Para poder construir esta estructura podemos utilizar la funci贸n GetEntryDialParams a la que pasamos una estructura s贸lo con el nombre de la configuraci贸n que queremos utilizar y el recoge el resto de los datos.

Los dos par谩metros siguientes se utilizan para un seguimiento as铆ncrono del estado de la conexi贸n. Como desde Visual FoxPro es bastante complejo la recepci贸n de mensajes del sistema nos centraremos en realizar conexiones donde la funci贸n no devuelva el control hasta que se realice todo el proceso.


Por 煤ltimo le pasaremos una variable por referencia para que introduzca en ella el manejador de la conexi贸n establecida.

Como ejemplo hemos creado una funci贸n que recibe el nombre de la entrada en el phonebook que queremos utilizar, realiza la llamada y comprueba que ha sido satisfactor铆a, devolviendonos el manejador de la misma.

******************************************
***
*** Realiza una llamada y devuelve el
*** manejador a la conexi贸n
***
******************************************
LPARAMETER cConexion

*** Declaraci贸n de las funciones del API DECLARE Integer RasDial ;
IN RASAPI32.DLL ;
Integer RasDialExtensions, ;
Integer Phonebook, ;
String @ RasDialParams, ;
Integer NotifierType, ;
Integer Notifier, ;
Integer @ hRasConn

DECLARE Integer RasHangUp ;
IN RASAPI32.DLL ;
Integer hRasConn

DECLARE Integer RasGetEntryDialParams ;
IN RASAPI32.DLL ;
String @ PhoneDirectory, ;
String @ RasDialParams, ;
Integer @ IsPassword

DECLARE Integer RasGetErrorString ;
IN RASAPI32.DLL ;
Integer ErrorValue, ;
String @ MessageBuffer, ;
Integer BufferLen

LOCAL cPhonebook, cRasDialParams, nResult
LOCAL nRasConn

*** Elminar blancos en el par谩metro pasado
cConexion = ALLTRIM( cConexion )

*** Preparar la estructura para los
*** parametros de conexi贸n
cRasDialParams = wordtoc(1052) ;
+ cConexion ;
+ REPLICATE( CHR(0), ;
1045 - LEN( cConexion ) )
cPhonebook = chr(0)
nPasswords = 0

*** Obtener los parametros de conexi贸n
nResult = RasGetEntryDialParams( ;
@cPhonebook, ;
@cRasDialParams, ;
@nPasswords )

*** Preparar variable para el retorno
*** del manejador
nRasConn = 0

*** Realizar la conexi贸n
nResult = RasDial( 0, 0, ;
@cRasDialParams, 0, 0, @nRasConn )

*** Comprobar si hubo error y mostrar
*** mensaje si lo hubo
IF nResult # 0

PRIVATE cMensaje
cMensaje = SPACE(256)

IF RasGetErrorString( nResult, ;
@cMensaje, LEN(cMensaje) ) # 0

ERROR "Error no determinado en " ;
+ "Acceso telef贸nico a redes. (" ;
+ LTRIM( STR( nResult ) ) + ")"
ELSE

ERROR "Acceso telef贸nico a redes: (";
+ LTRIM( STR( nResult ) ) + ") " ;
+ ALLTRIM( cMensaje )

ENDIF

*** Colgar por si qued贸 inestable
*** la conexi贸n
RasHangUp( nRasConn )

*** Retorno con error -2
RETURN -2

ENDIF

*** Retorno del manejador de la conexi贸n
RETURN nRasConn
Debemos hacer notar que se est谩 utilizando un programa llamado wordtoc para convertir un n煤mero a un tipo de dato DWORD capaz de introducirse en el buffer que utilizamos como sustituto de la estructura C original. En otros ejemplos utilizaremos el programa ctoword para poder obtener un n煤mero desde el buffer. Este es el c贸digo fuente de ambos programas:

*** WORDTOC
*** Combierte un n煤mero en un buffer
PROCEDURE WORDTOC
LPARAMETER nNumber
RETURN CHR(BITAND(255,nNumber)) ;
+ CHR(BITAND(65280,nNumber)%255) ;
+ CHR(BITAND(16711680,nNumber)%255) ;
+ CHR(BITAND(4278190080,nNumber)%255)

*** CTOWORD
*** Combierte un buffer en un n煤mero
PROCEDURE CTOWORD
LPARAMETER cBuffer
RETURN ASC(SUBSTR(cBuffer,1,1)) ;
+ ASC(SUBSTR(cBuffer,2,1))*256 ;
+ ASC(SUBSTR(cBuffer,3,1))*65536 ;
+ ASC(SUBSTR(cBuffer,4,1))*16777216
Cerrar una conexi贸n RAS
Una aplicaci贸n elegante no deja sus conexiones abiertas una vez que no le son necesarias o cuando la aplicaci贸n se cierra. Lo mejor es preguntarle al usuario si desea que cerremos la conexi贸n o bien desea mantenerla abierta. Para cerrar una conexi贸n abierta con RasDial utilizaremos la siguiente funci贸n:

DECLARE Integer RasHangUp ;
IN RASAPI32.DLL ;
Integer hRasConn
Esta funci贸n requiere el manejador de la conexi贸n y colgar谩 la l铆nea. Es necesario esperar algunos segundos antes de volver a utilizar la l铆nea, pues es habitual que 茅sta no se encuentre disponible inmediantemente despues de ser colgada.

Como ejemplo hemos realizado un peque帽o programa que corta la conexi贸n de la que pasemos el manejador, esperando 3 segundos antes de devolver el control.

******************************************
***
*** Cuelga una conexi贸n realizada y de la
*** que dispongamos un manejador
***
******************************************
LPARAMETER nRasConn

*** Declaraci贸n de las funciones del API DECLARE Integer RasHangUp ;
IN RASAPI32.DLL ;
Integer hRasConn

DECLARE Integer Sleep ;
IN Win32API ;
Integer Milliseconds

LOCAL nResult

*** Realizar el cierre de la l铆nea
nResult = RasHangUp( nRasConn )

*** Realizar una pausa de tres segundos
*** para asegurar el colgado
=Sleep(3000)
ENDIF

*** Retornar lo devuelto por la funci贸n
RETURN nResult
Obtener las conexiones ya establecidas
Antes de abrir una conexi贸n por Dial-Up Networking es necesario saber si ya exist铆a una conexi贸n con esa configuraci贸n y de esta forma evitar intentar realizar dos veces la misma conexi贸n. Para saber qu茅 conexiones est谩n abiertas se utiliza la siguiente funci贸n del API de RAS:

DECLARE INTEGER RasEnumConnections ;
IN RASAPI32.DLL ;
STRING @ RasConnectionsBuffer, ;
INTEGER @ dwSize, ;
INTEGER @ nCount
Esta funci贸n utiliza una estructura tipo matriz de estructuras RASCONN. Como en los casos anteriores debemos crear un buffer para contener esta matriz de estructuras y luego obtener los datos por la posici贸n de los elementos de la estructura dentro del buffer.

Como ejemplo hemos creado un programa que crea una matriz con el nombre recibido como par谩metro e inserta en la misma la informaci贸n sobre las conexiones activas en ese momento.

******************************************
***
*** Construye una matriz con todas las
*** conexiones RAS abiertas
***
******************************************
LPARAMETER cArrayReturn

*** Declaraci贸n de las funciones del API
DECLARE INTEGER RasEnumConnections ;
IN RASAPI32.DLL ;
STRING @ RasConnectionsBuffer, ;
INTEGER @ dwSize, ;
INTEGER @ nCount

DECLARE INTEGER RasGetErrorString ;
IN RASAPI32.DLL;
INTEGER ErrorValue, ;
STRING @ MessageBuffer, ;
INTEGER BufferLen

*** Creaci贸n de una estructura tipo RASCONN
cConexion = wordtoc(412) ;
+ REPLICATE( CHR(0), 408 )

*** Creaci贸n de una matriz con esa
*** estructura
cConexiones = REPLICATE( cConexion, 16 )

*** Variable con el tama帽o de la matriz
nSize = LEN( cConexiones )

*** Variable en la que se retorna el
*** n煤mero de entradas encontradas
nCount = 0

*** Llamada a la funci贸n para obtener
*** la informaci贸n
nResult = RasEnumConnections( ;
@cConexiones, ;
@nSize, ;
@nCount )

*** Si existe alguna conexi贸n abierta
IF nCount > 0

*** Dimensi贸n de la matriz como p煤blica
PUBLIC ARRAY &cArrayReturn.[nCount,4]

*** Extracci贸n de los datos desde la
*** matriz de estructuras
FOR nPos = 0 TO nCount - 1

*** Obtener una Estructura
cConexion = SUBSTR( ;
cConexiones, ;
( nPos * 412 ) + 1, ;
412 )

*** Handle
&cArrayReturn.[nPos+1,1] = ctoword( ;
SUBSTR(cConexion,5,4))
*** Nombre
&cArrayReturn.[nPos+1,2] = STRTRAN( ;
SUBSTR(cConexion,9,257), CHR(0))
*** Tipo
&cArrayReturn.[nPos+1,3] = STRTRAN( ;
SUBSTR(cConexion,266,17),CHR(0))
*** Device
&cArrayReturn.[nPos+1,4] = STRTRAN( ;
SUBSTR(cConexion,283,129),CHR(0))

NEXT

ENDIF

*** Retorno del n煤mero de elementos que
** se han encontrado

RETURN(nCount)
Algunas ideas
El espacio se acaba, pero es interesante mostrar dos cuadros de di谩logo que se pueden encontrar en el disco de la revista y que ejemplifican el posible interface de una aplicaci贸n cuando esta utiliza Internet. S贸lo son un esquema, pero puede servir de base para una aplicaci贸n.

Para configurar el sistema de marcado, si es que se utiliza este y no un Proxy o un Router, podemos mostrar un formulario similar a este:




Cuando se solicita permiso para realizar una conexi贸n en la que realizar谩 una comprobaci贸n de la versi贸n de la aplicaci贸n y bajar posibles actualizaciones podr铆a mostrar un mensaje similar a este:




Con estos detalles nuestra aplicaci贸n puede empezar a utilizar un sistema de Dial-Up Networking con la mayor facilidad.

El API aqu铆 descrito no es m谩s que una peque帽a muestra de las posibilidades del RAS, pero de momento es suficiente para nuestros propositos. En los pr贸ximos art铆culos veremos como aprovechar esta conexi贸n por medio de protocolos como FTP y HTTP.


Pablo Almuniapertenece al grupo de Consultor铆a y Control de Calidad de la Unidad de Inform谩tica de MAPFRE. Se puede entrar en contacto con 茅l por Email en [email protected]

David Martinez
05 de Enero del 2004
Debes utilizar un API de comunicaciones RAS, el de microsoft no te lo recomiendo ya que desde fox no va demasiado bien es mejor que uses uno de terceros por ejemplo el de Mabry va bastante fino aunque es de pago merece la pena.

Saludos.

David M.
---
CEINTEC http://www.ceintec.com