Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Setting Up A Com Server

Status
Not open for further replies.

BrendanChandler

Programmer
Sep 12, 2000
28
GB
I have a VFP 6 application containing several databases of names and numbers to describe it in simplistic terms. A want to link this system to a new telephone system that is being installed so that as well as users clicking 'Find' in my app to locate records using name, telephone no etc, when the phone rings I want the 3rd party phone system to send my app a message to tell me the number which is ringing so that I can return the name of the person in the database to whom the phone number belongs (there could be several in some instances). The phone software should present a list of possibles and if the user selects one it will pass details back to my app so that I can locate the selected record and display the appropriate input screen.

The telephone people suggest COM is the best way but as usual cannot really help with VFP and I have done no VFP COM server stuff before now other than some automation stuff to control Word and Outlook.

I have worked out so far that I can put the following code at the end of my top level PRG file in my app

DEFINE class phonestuff AS CUSTOM OLEPUBLIC
PROCEDURE phonesearch
Parameters ptelephone
do ismess with "Some one just called on "+ptelephone
ENDPROC
ENDDEFINE

I compile the app as MYAPP.EXE, ran it and accessed the server from another VFP session using

oTest = CREATEOBJECT("myapp.phonestuff")
cName = oTest.phonesearch("1234")

It worked! I thought this is easy then the problems started - as I started to expand the code to interrogate the database in the app, load the appropriate forms etc I found that tables that are open throughout the app where not accessible to the com object, neither were forms or other classes that are present throughout the app.

Question - what do I need to do in order to make everything visible to the COM object that has already been loaded in MYAPP.EXE? Are there any more pitfalls I should be aware of as I take this development further?

Any help really appreciated. Thanks
 
I found that tables that are open throughout the app where not accessible to the com object[/code]

Can you explain this statement? Is the COM on the same server as the tables? Is there a connectivity issue? Is there an error message?

Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
If you run your app as in
Code:
DO myapp.exe
and a few lines earlier or later you create a COM object
Code:
oTest = CREATEOBJECT("myapp.phonestuff")
then you have 2 completely independent processes that don't share anything apart from some class code. Your COM server is nothing but an object of that one class "phonestuff" and as long as that class doesn't open tables you won't see any.
Also, your server doesn't have any GUI output and although it is possible within limits you should avoid even Messageboxes.

Volker/
 

Brendan,

You really need to make the COM app completely independent. You said that your DEFINE CLASS was at the end of your main PRG. You don't really want a main PRG for a COM app. The whole thing should be encapsulated in a single class, with the methods of that class performingall the functionality of the app.

You would then open all the needed tables in the Init of the app, and also make all the environment settings, such as the default directory and the search path. Be sure not to open any tables exclusively if other apps will be using them at the same time.

Volker mentioned avoiding UI output. I believe this is only necessary in the case of remote COM servers, such as in the case of web-based apps. Provided your COM component is running on the actual machine that the user is using, there should be no need to avoid output to the screen (as far as I know).

Apart from that, it looks like you are on the right track.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

My sites:
Visual FoxPro (www.ml-consult.demon.co.uk)
Crystal Reports (www.ml-crystal.com)
 
Hey - slow down guys, remember COM stuff is completely new to me. Done a bit with classes but 'encapsulating' the application etc is going way over my head here. Let me try to explain myself better and perhaps you can ensure I am on the right lines then lead me 'slowly'! My app is a standalone EXE. It is a membership database in fact with tens of thousands of records. Members call the office then people will process member applications, take bookings, record payments etc in my app. With the new system, when the phone rings they want a screen to tell them who is ringing. At that point they may wish to continue what they are doing in my app or click a button to have my app take them straight to the member screen for the person who is calling.

You say that the COM object is separate from my app? How does that work? If it is separate then how does it get to the right screen for them to carry on dealing with that member? I added the class definition to the top level PRG in the hope it would make it visible throughout the PRG, maybe this is completely the wrong thing to do thats why I need help. If it is totally independant how do I expose all the functionality of the main app within the COM? The main app is over 10 years of VFP development - is this easy to do? What do the users then load the COM instead of the APP or the COM and the app. My questions probably don't even make sense here as I am so lost!!! Please help. Thanks
 
You may have a wrong understanding of what a COM is (what it is meant to be or do).
As Mike Lewis suggested a COM is a separate application that is meant to run independently for any applications.
Normally COM do not have an interface (although COM exe can support limited inteface). The advantage with COMs is that they may be used by other applications and languages (VB could use a VFP COM application).
I'm not sure you need a separate COM to achieve what you need.
The telephone people suggest COM is the best way

Have they explained why this is the best way? Were they aware that you already had an application written in VFP, this is where you need to add the extra functionality?
It just sounds like you need an additional method or two get the caller's ANI and do a search in your data, find the record and load up your form.




Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
Brendan,

Sorry if we were running ahead of things. I got the impression from the code you posted that you were already quite clued up on COM. Now that I have read your post more carefully, I can see where you said that you had done no COM server stuff before.

It looks like we need to go back to first principles here. What exactly are the telephone people providing in the way of an interface? Do they themselves provide a COM component that you can call? Or an API call? Or what?

As Mike Gagnon suggested, maybe we shouldn't take their recommendation too much at face value. After all, they probably don't know anything about VFP or what it is capable of.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

My sites:
Visual FoxPro (www.ml-consult.demon.co.uk)
Crystal Reports (www.ml-crystal.com)
 

Just to add to Mike's question, I'm not sure what your setup is, but I work for a telecommunication company (we run our own switches) and I can detect the caller's ANI and display the callers information, without the use of COMs.

Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
Thanks for your patience with me guys. I must admit the telephone people are not being incredibly helpful. They keep giving me 'tasters' then leave me high and dry when it comes to implementing the detail. They claim they are used to working with COM servers to do this in many applications such as VB, Delphi, C++ etc. They have touched on VFP before but their knowledge in it seems very limited indeed. From what I understand from them COM is a means of interfacing between two entirely separate systems with neither needing to know the language hidden beneath the other. Using COM they can then interface with any system that supports COM. From what you are saying it sounds fine for them to pass me something, for me to query the database and return something back to them and then for them to pass me something back to tell me which of the 'potential' records to go to. I had not realised all the functionality of my existing app would not be available for access here and that I would have to maybe duplicate effort within the COM but from their point of view I can see how they can have an easy task at their side interfacing to other systems by simply changing the COM call name and parameters. They originally wanted to access my tables directly through ODBC but I talked them out of that due to the complexity involved (not just a members database but also enquiries, suppliers, lapsed members, paid up members, joint members etc) - I don't want to have to explain all that to them and then be limited in what I do later in terms of changing structures, adding new tables etc in case it messes up anything they write. Much better that I control the code myself. They conceded that that is a common request from other people they deal with and suggested the COM route. They know that I have a full app running here already.

If we don't do it this way, what are the other options that I could suggest to them? Perhaps running their own COM server that I poll, perhaps on a timed event for example? Or perhaps I still have the COM object which they pass a number to, then it queries the database and returns a list of options back to them, then they call another method in my COM to say which of the potential records are to be selected which sets a property in the COM indicating the selected record. Within my app I then have a timer event or wait state process that calls my COM to query that property and if it finds a value in it, it clears the value and goes to the relevant screen for that record. Does this sound any more like it?

Thanks again.
 
I want the 3rd party phone system to send my app a message to tell me the number which is ringing

Can you explain at the moment how you are dectecting "who is calling". Are you getting this information from your phone system? Or are you not at that point yet. Are you receiving this info via a port in your computer, if so do you have a port 'listener'?

Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
Mike,

I am in Derbyshire, my customer is in Birmingham and his phone system has not been installed yet, we are hoping to have software available before it gets installed. All dealings have been by phone and email with the phone company. I have not seen the telephone system or even a spec for it. I would not know how to listen on a port - again not an area I have ever ventured into - most of my VFP knowledge is straight forward database input, manipulation and reporting with a little MS Office automation thrown in. My understanding is that they are supplying their own software with the system which will interface with the user's PC (there are 5 users, each who will have a phone and will be running my app). When I tell them the name of my COM server and the methods and properties in it they will program their software to interface with it. They have suggested a couple of simple methods already descibed ie to receive a number from them, interrogate the database for a match and return back one or more matched record details. They would then display that list to the user using their interface so that the user can opt to either just glance at who is calling before they lift the receiver or can select a record which will call a second method in my COM to tell me to go to the selected record. How I achieve that last bit is up to me and still not too clear. They have apparantly done this kind of thing lots of times with other COM servers (including I assume VFP) but they cannot supply the detail I need to get to grips with it. I have requested that if they cannot supply the detail then perhaps they can supply a contact at a company that has already done this but that information has also not been supplied to date.

Thanks
 
This is how I would handle it.
I'd figure out how they (their software) can supply you with the calling ANI.
At this point, after thinking about the concept I would use a COM (and application that would sit in between the phone system and your application). The reason I would go with a COM is because a COM can be used by other applications, not just VFP, which would help to phone company to modify their software to send the phone number as a parameter to yoour COM. This COM would 'listen' for any in comming ANIs. As soon as it receives one it send it to your application which has a timer (in the _screen) that just waits for in comming numbers, and as sonn as it gets one it locates the record and pops up the appropiate screen.
All the software would have to do is instantiate the COM and send the ANI to it, your COM would then put this ANI in a temp table, and your app (with its timer running) would check every few seconds (or even every second) to see if there is a new record in the temp table.



Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 

The concept would be similar to when you have Outlook or MSN messenger running and you receive an e-mail and right away the application advises you that you have received an e-mail.
Another suggestion (to avoid the COM) might that the phone software, when a call comes in, generates a small textfile, with either the phone number in it, or even naming the file name as the phone number, and your screen timer (mentionned above) would detect a new file and deal with it (and deleting it once it is used). I made this suggestion as I'm not sure with a COM that you may end up "loosing" precious seconds, and that the whole process might too slow to get a quick reaction from your software.

Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
One way to have a more immediate reaction from your app would be to use a winsock class, which would listen to requests. If the "telephone people" want to work with COM, make your little COM server send the request to your app via winsock. That way you don't need to poll for requests in a timer event, but let winsock do that stuff for you. As that socket communication is between your COM server and your app only, you can use your secret port and define your own protocoll for the request messages, so no one may interfere. It's a local thing anyway between COM server and App running on the same computer. Your app may send answers directly to the COM-server or via winsock.

One additional suggestion: If you make your COM server a Single Instance server, there can be only one instance running and the phone software and/or your app may be the one CREATING that COM server object, while the other side will use GETOBJECT() (or something similar) to get an object reference to the same COM object and thereby both phone software and your application will be docked to the same COM server instance, which might also be very helpful.

Bye, Olaf.
 
Hi guys, I'm back. Sorry about the delay I have had to drop this for a couple of weeks but just picked up again. I now have a .DLL called telephone.dll. It contains a class called telephone marked as OLEPUBLIC. It has methods as follows

INIT
set exclusive off
open database bookit
use memship in 0
use members in 0

DESTROY
close data all

CONTACT
parameters pref
if seek(pref,"members","ref")
return allt(trim(members.firstname) + ", " + trim(members.lastname)
return "Not found"
endif

There is also a property which I have called GOTOREC which initially contains blanks and will be used to store details of a selected member later

I have compile the project also called telephone containing the class called telephone using the 'single threaded com server (dll)' option.

In my main app I have created a timer using the following code to look at the property GOTOREC in the com server at regular intervals and display its contents (obviously it will do a lot more once I get this bit working!)

define class bookittimer as timer
enabled = .t.
interval = 1000
procedure timer
wait window otelephone.gotorec timeout .5 nowait
endproc
enddefine

Near the top of my main program file I use the following to creating the DLL instance and to initiate the timer

otelephone = createobject("telephone.telephone")
otimer = createobject("bookittimer")

All works fine so far. I start my app and every second I see a wait window showing me that gotorec property is still empty.

Finally I put together a program to simulate what the telephone people will be doing. For test purposes it simply calls a method in the com server passing it a member reference that it knows about 001001. A dialogue then appears generated by my isconfirm function in my utillib procedure library displaying the located member name and asking if I wish to select it. This bit works so the contact method checks out OK. Next it sets the gotorec property in the COM server to the located member ie 001001 and confirms this with a wait window

otelephone = createobject("telephone.telephone")
cname = otelephone.contact("001001")
set procedure to progs\utillib
if isconfirm("Go to "+allt(cname)+"?")
otelephone.gotorec = "001001"
wait window otelephone.gotorec
endif

Although it looks like it has updated the COM server property properly, the wait window in my main app is still showing a blank value every second, it does not seem to be looking at the same instance of the com server - the main app and test program seem to be addressing two separate areas of memory rather than the same! Have I done something wrong or missed something? My understanding of the single thread compile was that it should be the same area? I have tried multi thread and got the same results. Any help to finish this last bit off really appreciated. Thanks

 
Have I completely misunderstood the terms in process and out of process and mixed these up with single and multiple threads to get 2 + 2 to make 5 above? Perhaps a property in a DLL cannot be shared between my main app and a 2nd program? Am I trying to do something that on relexion I should really do by storing the value to a table, not to a property in the com server?

Further more, when I return a value to the phone client softwsre, there could perhaps be multiple entries if there are several members at the same number, company names could be involved and perhaps other details. What is the best structure to return? I suppose I could use a character string but being restricted to 255 characters may be limiting. I could store to a text file a list of comma delimited entries but might have to worry about file access issues. Are there other structures I could return that are more suited to a list of records that can easily be used at the other side without it having to be a FoxPro client?

Thanks
 
Am I trying to do something that on relexion I should really do by storing the value to a table, not to a property in the com server?

That is correct, if you store a value to a property of a COM on the first pass, on the second pass that same value will not be available.

If many things are comming in all at the same time, I would suggest the use of a table, creating records as they come in.


Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
Mike,

Thanks for the confirmation. I will use a table to store the incoming call number. In terms of passing back a list of names and contact details that match that number to the phone people's software via the COM server, though, so that the phone people can present that list in their interface before getting the user to select one and pass that back to me - what structure do you suggest I pass back? Are you suggesting a table there too, in which case I will need to get them looking at ODBC?. 255 chars string would probably be too short or are there bigger strings or structures in VFP6 that could be passed back and they could read without knowledge of FoxPro or having to use ODBC? Thanks
 

Ièm not sure what they require, in order for this to work. You can pass a memo field or a textfile.

Mike Gagnon

If you want to get the best response to a question, please check out FAQ184-2483 first.
 
Mike,

Not sure what language they are using, they seemed to have a lot of knowledge of VB and C++. Can I assume that these languages can handle a memo field for example, is that not very VFP? Is it possible to return a recordset and would that be better? I have not done any SQL Server programming in VFP but have done a bit of ASP programming and know that that is very VB and also uses recordsets. Is there a set of commands that I can use in VFP to extract a selection from a table to a record set that can then be passed back. Sorry I'm a bit weak in this area although well experienced on the SQL SELECT command but I don't think that helps here unless I get it to a cursor using that and somehow convert it to a record set to be passed. All syntax help appreciated. Thanks
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top