“Making a phone call with a .NET application was THAT simple? And I always thought [that] only a real savvy can do such a state-of-the-art work.”

were the comments given by a friend of mine when I showed him this demo project. But the truth is; that this task was never so easy until a real savant made it easy as pie for all of us. Thanks to Julmar Technology ( http://www.julmar.com/ ).

These folks have done a magnificent work and provided us with a class library built upon TAPI 2.x (distributed with Windows XP). TAPI, so far does not give any interface which can be used in .NET to make a phone call. Nonetheless, with the class library we have in our hand now, making a phone call is as easy as instantiating an object and calling its appropriate functions. So let’s see the magic.

Creation of Phone Caller Application:

The main logic behind this application is; we want to display a simple Listbox with a few persons’ information populated in it. Each person will have an ID, Name, Phone Number etc. When user selects a person in the list it will show person’s information in the textboxes present on the form. Phone Number textbox has a button in front of it. Clicking this button will initiate a phone call. Let’s quickly take a look at how this form is going to look like:

So we’ll create a simple windows application and add references to our DLL file which gives our application the ability to make phone calls.

I’ve created a small class of Person. This class contains some private data members and their corresponding public properties, followed by 2 overloaded constructors. That’s how the class looks like, and I’ve written the class within frmPersons.cs itself:

At line 01, TapiManager type variable is declared at class level. At line 02, I’m creating a class level variable which will contain all the persons information used for this application. Line 03 has two string variables lineName will keep the name of the telephone line tapi manager will use to make phone calls. logEntry will keep all the log of the phone calls made or attempted to make during an application session. Line 04 is standard form constructor. Now let’s see form load event:

// Line numbers are given for understanding and are not part of the actual code

Line 01 initializes form level tapiManager. In line 02 I’m calling GetPersonList() method which will create a list of persons. Person information is hard coded in this method and then saved in class level lstPersons variable. The same list of person will be displayed in our lstNames listbox in the method ShowData(), line 03. In real world application, GetPersonList() method will get list of persons from database instead of getting hard coded persons. Line 04 sets the name of the telephone line. When we call tapiManager’s initialize method it gets a list of all the lines attached to the computer, but we are interested in only the one connected with modem, which in most cases is present at 0th index. Now let’s see our GetPersonList():

For simplicity, I’ve used the selected index property of the listbox to refer the person in the generic list of persons, a class level variable. In real world application this logic won’t be that simple. Before I jump to the method which actually makes phone calls for us let me explain a few very important methods that are responsible for some functionality like log entry and closing the application and shutting down the tapiManager. So let’s take a look at them one by one.

When form is closing I want all the activity done during the form was open to be saved in a log file. For this purpose I keep on saving user’s each and every activity in a class level string variable separated by “|” sign (explained below) and in this event I open a log file with stream writer, split the string on the basis of “|” and insert activities line by line.

After all these methods this is the time for showing and explaining what magic the phone button does which actually makes a phone call.

privatevoid btnCall_Click(object sender, EventArgs e)

{

if(this.txtPhone.Text.Trim().Length > 0)

this.MakePhoneCall(this.txtPhone.Text);

}

When Call button is clicked, it simply checks the phone number text box’s text length. If it is more than 0 then it passes it to MakePhoneCall method.

TapiLine is one of the classes given in Atapi.dll. This class is created by tapiManager’s method GetLineByName, line 01. After checking line object for not being null (line 02) we are ready to open the line for making a phone call. Lines 03, 04 check whether line is not open already, if not then open the line passing enum MediaModes’s DataModem. Lines 05, 06 and 07 are assigning event handler methods to different events line object generates while making a phone call. Line 08 double checks whether the phone number is not empty. Line 09 instantiates parameters object of Atapi library. This object can be used for different kind of settings in phone making process; e.g. I set dial pause to 2000 (2 second). Dial pause means when line opens and detects tone, after detecting the tone it will give a pause of 2 seconds. This is useful if you are sitting in your office and your desk phone is connected with a telephone exchange and you need to enter a number to get out of exchange and then you can enter outside number. You can do so by entering a number in textbox, prefixed by the number that takes you to out of telephone exchange, suffixed by a comma “,”. For example, I have to enter 9 to make outside phone calls in my office; I would enter a number 9,262-527-1234. 9 would take me out of the local phone exchange “,” will give a 2 second dial pause and then rest of the number will be dialed. After making ground, we are now ready to make phone call; line 11 is calling MakeCall method of line object. This will return a Call object which can be used in making log entry. Sometimes line’s MakeCall method throws an exception. I could not understand the reason and found the error is generated on random basis. The work around is given in the catch block; if exception has 0x80000005 number in its text then all we need to do is, shutdown tapiManager, re-initialize it and call the call MakePhoneCall method recursively. That’s exactly what I’m doing in lines 14, 15, 16 and 17.

After MakePhoneCall method there is nothing of vital importance in this code. So let’s just quickly see what event handlers of line object are doing.

This method prefixes date and time stamp with every log entry sent by any method. After running a couple of test calls, call log on my machine looks like this:

Before I end this article, for novice programmers, I want to show how you have to connect telephone chords with phone and computer. For this purpose you need 3 chords, one connected to landline port on the wall like this:

Secondly, this chord should be connected to a connector with two other wires as shown below:

One of these two chords would go into the computer’s modem like this:

And finally the last chord needs to go in the telephone set:

That’s it, simple and clean. After creating this demo application, you have become a savvy programmer who can develop .NET applications having ability to make phone calls. Don’t forget to give me your feedback on this article and also feel free to contact me if you have any questions.

hello…
i tried your example and i m facing few problems in that,
the project is building successfully and when i am trying to connect to another phone it work very well but i can not answer the phone call..i can listen voice of call reciever but recieving person can not listen caller voice.. if you have solution then plz reply …

@ Shrikant: At this point I’m not sure if this code can be used for SMS; I think you’ll have to explore further and put some effort. Please let us know as well, if you find out something good.

@ Jyotsna: Are you sure you connected all the wires correctly as I explained above? We were able to make phone calls with this configuration in United States over land lines and cell phones both. Did you try lifting call sender’s phone receiver and talk? We noticed that some modems were half-duplex and did not transfer voice in both directions. Keep on posting and let us have your feedback…

I have a general question, I made my application by getting help from Ur article and its doing great, I wanted to play back a wav file, but when I request for playback terminal its unable to connect and I dunt know whats the reason can it be due to my modem ?? please can You reply me in detail about playback terminal, Thanks 🙂

hi, thanks for such app. but i have problem. when i make a call and callstate become: connected, how can i notify the called person picked up the receiver(phone) or just dropped it? i mean i wanna to determine is my partner answered to my call, or not. the call state events just say connect, when dialling finished, and disconnect when the call is over, no reporting what happened between to states.
i really appreciate you if help me.

@ Ali & techind: At this point I’m not sure if this code can be used for the purpose you are trying to achieve; I think you’ll have to explore further and put some effort. Please let us know as well, if you find out something good.

Really a nice and helpful post. I have created a c# windows form application and did all the things you have done. I But I got the following error:

“Could not load file or assembly ‘Atapi, Version=1.1.3.30, Culture=neutral, PublicKeyToken=6148c7b92dc86471’ or one of its dependencies. An attempt was made to load a program with an incorrect format.”

And it is not running the application at all. I’m using Windows 7 and 64 bit machine.

Did you get Atapi dll from their website? Link of their website is given in the article above. See if they have made a dll for 64-bit machines available. If they have, then you have a chance, otherwise, you can request them to update their class libraries. Good Luck!

Once I changed the platform from Visual Studio it is running. But, the problem is it is not running from the other side, I wanted to make a phone call and play a voice message to that number. Do you have any reference to this work? I would really appreciate if you could help me doing it.

i tried your example and i m facing few problems in that,
the project is building successfully and when i am trying to connect to another phone it work very well but i can not answer the phone call..i can listen voice of call reciever but recieving person can not listen caller voice.. if you have solution then plz reply …

You have to pick up your phone’s receiver and then speak. This software is not designed to use your PC’s mic and speakers to exchange voice data over the phone line. Albeit I’m planning to write such a component.

for example you are the caller and calling on my number then defiantly on my phone set there will be ur number but i wanted to show that number on my PC
from here U are making the call but i want to see the caller number who is calling on my number

Ok, this particular project is for sending outgoing calls from pc to phone line only, and not for receiving incoming calls . Not that it’s not possible to achieve but in this project you won’t find it. So please go ahead and put some effort to get it done.

Rajesh, you don’t need headphones attached with the computer, however you do need headset attached with the phone through which you can talk and hear other person’s voice. There are no configurations other than what is mentioned in the article above. So, try it and I hope it will be all good. Let me know if you need the project source code. Good luck!

Hi, very useful article but I’m experiencing a very annoying problem; I keep getting this error: “Could not load file or assembly ‘Atapi, Version=1.2.0.0, Culture=neutral, PublicKeyToken=6148c7b92dc86471’ or one of its dependencies. The system cannot find the file specified.” Do you know why I might be getting this – any help would be greatly appreciated! Thanks.

lineopen failed[0X8000002F]invalid media mode
=====================
is it necessary to connect one line to landline phone

i have airtel connection i have three cable one come from main connection there is connection in between what u have told in above one for modem one for phone which line is used for laptop and which is used for phone please tell me onne the connector line for modem and line to connect phone .
plz plz reply me one your site or on my email id : afsar_sm2002@yahoo.com

TapiLine line = tapimanager.GetLineByName(this.lineName, true); I am gettint null for lineName. So the app is not moving forward. Can you please explain me why am i gettting null for lineName? What mistake have i made and any solution for that?

This is the right site for everyone who hopes to understand this topic.
You know so much its almost hard to argue with you (not that I really would
want to…HaHa). You definitely put a brand new spin on a subject that has been discussed for decades.

Hi! I could have sworn I’ve visited this blog before but after going through some of the articles I realized it’s new
to me. Regardless, I’m definitely happy I stumbled upon it and I’ll be book-marking it and checking back often!