I'm rewriting a C++ TAPI app I wrote a while ago in C#. Everything
works fine for the first call. Unfortunately, all subsequent calls are
completely ignored by TAPI until I restart the app again.
I remember running into this same problem with my original C++ code and
it was being caused by my failure to release all call related tapi
resources. As a point of reference the C++ app has been running quite
well for over a year.
Anyway, I beleive I'm releasing all the tapi interfaces when I'm done
with them but nothing I've done has solved the problem. I'm at a
complete loss as to what might be causing the problem. Any thoughts
would be greatly appreciated.
Here's the code:
=============== =========
using System;
using System.Drawing;
using System.Collecti ons;
using System.Componen tModel;
using System.Windows. Forms;
using System.Runtime. InteropServices ;
using TAPI3Lib;
namespace CallManager
{
/// <summary>
/// Summary description for TapiMsgWindow.
/// </summary>
public class TapiMsgWindow : System.Windows. Forms.Form
{
public delegate void TapiInitializat ionDelegate(obj ect sender, bool
success);
public event TapiInitializat ionDelegate TapiInitializat ion;
public delegate void CallNotificatio nDelegate(objec t sender);
public event CallNotificatio nDelegate CallNotificatio n;
public delegate void CallStateDelega te(object sender,
TAPI3Lib.CALL_S TATE callState);
public event CallStateDelega te CallState;
public delegate void CallInfoDelegat e(object sender,
CALLINFOCHANGE_ CAUSE cic);
public event CallInfoDelegat e CallInfo;
public delegate void CallerIDEventDe legate(object sender,
CallerIDInfo cidInfo);
public event CallerIDEventDe legate CallerIDEvent;
public enum MEDIATYPE
{
MediaAudio = 8,
MediaModem = 16,
MediaFax = 32,
MediaVideo = 32768,
}
private MainForm _ParentForm = null;
private TAPI3Lib.TAPICl ass _TAPI = null;
private ITAddress ListenAddress = null;
private ITBasicCallCont rol Call = null;
private int RegEventsResult = -1;
private int mediaTypes = 0;
private bool IsNewCall = false;
private int CurrentRingCoun t = 0;
/// <summary>
/// Required designer variable.
/// </summary>
private System.Componen tModel.Containe r components = null;
public TapiMsgWindow()
{
InitializeCompo nent();
}
public TapiMsgWindow(M ainForm parentForm) : this()
{
_ParentForm = parentForm;
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Disp ose();
_TAPI.Unregiste rNotifications( RegEventsResult );
_TAPI.Shutdown( );
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeCompo nent()
{
this.components = new System.Componen tModel.Containe r();
this.Size = new System.Drawing. Size(300,300);
this.Text = "TapiMsgWindow" ;
}
#endregion
public bool InitTAPI()
{
bool result = false;
_TAPI = new TAPI3Lib.TAPICl ass();
try
{
_TAPI.Initializ e();
_TAPI.Event += new
ITTAPIDispatchE ventNotificatio n_EventEventHan dler(OnTapiEven t);
result = SelectAddress() ;
}
catch(Exception ex)
{
MessageBox.Show (ex.Message);
result = false;
}
if(TapiInitiali zation != null)
TapiInitializat ion(this, result);
return result;
}
private bool SelectAddress()
{
bool result = false;
ITCollection addresses = (ITCollection)_ TAPI.Addresses;
ITAddress curAddress = null;
ListenAddress = null;
//Careful here. The array is 1 based NOT 0 based;
for(int i = 1; i <= addresses.Count ; i++)
{
curAddress = (ITAddress)addr esses[i];
if(curAddress.S tate == ADDRESS_STATE.A S_INSERVICE)
{
ITMediaSupport mediaSupport = (ITMediaSupport )curAddress;
// Get the supported media types...
mediaTypes = mediaSupport.Me diaTypes;
mediaSupport = null;
if((mediaTypes & (int)MEDIATYPE. MediaAudio) ==
(int)MEDIATYPE. MediaAudio)
{
ListenAddress = curAddress;
break;
}
}
}
// Did we find the address we were looking for?
if(ListenAddres s != null)
{
RegEventsResult = _TAPI.RegisterC allNotification s(ListenAddress ,
true, true, mediaTypes, 1);
_TAPI.EventFilt er = (int)(
TAPI_EVENT.TE_C ALLNOTIFICATION |
TAPI_EVENT.TE_C ALLSTATE |
TAPI_EVENT.TE_D IGITEVENT |
TAPI_EVENT.TE_C ALLINFOCHANGE |
TAPI_EVENT.TE_A DDRESS
);
}
else
{
MessageBox.Show ("No TAPI address selected");
result = false;
}
result = true;
return result;
}
private void OnTapiEvent(TAP I_EVENT TapiEvent, object pEvent)
{
switch(TapiEven t)
{
case TAPI_EVENT.TE_C ALLSTATE:
{
OnCallStateEven t((ITCallStateE vent)pEvent);
break;
}
case TAPI_EVENT.TE_A DDRESS:
{
OnAddressEvent( (ITAddressEvent )pEvent);
break;
}
case TAPI_EVENT.TE_C ALLNOTIFICATION :
{
OnCallNotifyEve nt((ITCallNotif icationEvent)pE vent);
break;
}
case TAPI_EVENT.TE_C ALLINFOCHANGE:
{
OnCallInfoEvent ((ITCallInfoCha ngeEvent)pEvent );
break;
}
case TAPI_EVENT.TE_P HONEEVENT:
{
Marshal.Release ComObject(pEven t);
break;
}
case TAPI_EVENT.TE_D IGITEVENT:
{
OnDigitEvent((I TDigitDetection Event)pEvent);
break;
}
case TAPI_EVENT.TE_G ATHERDIGITS:
{
OnGatherDigits( (ITDigitsGather edEvent)pEvent) ;
break;
}
case TAPI_EVENT.TE_C ALLMEDIA:
{
OnCallMediaChan ged((ITCallMedi aEvent)pEvent);
break;
}
case TAPI_EVENT.TE_T ONEEVENT:
{
OnCallToneEvent ((ITToneDetecti onEvent)pEvent) ;
break;
}
default:
{
Marshal.Release ComObject(pEven t);
break;
}
}
}
private void OnCallInfoEvent (ITCallInfoChan geEvent pEvent)
{
Console.WriteLi ne("CallInfoEve nt:");
Console.WriteLi ne(pEvent.Cause .ToString());
if(CallInfo != null)
CallInfo(this, pEvent.Cause);
try
{
if(pEvent.Cause == CALLINFOCHANGE_ CAUSE.CIC_CALLE RID)
{
if(CurrentRingC ount >= 2)
{
string callerIDName =
pEvent.Call.get _CallInfoString (CALLINFO_STRIN G.CIS_CALLERIDN AME);
string callerIDNumber =
pEvent.Call.get _CallInfoString (CALLINFO_STRIN G.CIS_CALLERIDN UMBER);
CallerIDInfo cidInfo = new CallerIDInfo(ca llerIDNumber,
callerIDName);
if(CallerIDEven t != null)
CallerIDEvent(t his, cidInfo);
}
}
}
catch(Exception ex)
{
MessageBox.Show (string.Format( "CallInfoEv ent failed with the
following exception:{0}", ex.Message));
}
finally
{
Marshal.Release ComObject(pEven t);
}
}
private void OnDigitEvent(IT DigitDetectionE vent pEvent)
{
try
{
byte digit = pEvent.Digit;
int digitMode = pEvent.DigitMod e;
}
finally
{
Marshal.Release ComObject(pEven t);
}
}
private void OnGatherDigits( ITDigitsGathere dEvent pEvent)
{
try
{
}
finally
{
Marshal.Release ComObject(pEven t);
}
}
private void OnCallMediaChan ged(ITCallMedia Event pEvent)
{
try
{
}
finally
{
Marshal.Release ComObject(pEven t);
}
}
private void OnCallToneEvent (ITToneDetectio nEvent pEvent)
{
try
{
}
finally
{
Marshal.Release ComObject(pEven t);
}
}
private void OnAddressEvent( ITAddressEvent pEvent)
{
ADDRESS_EVENT addressEvent = pEvent.Event;
Marshal.Release ComObject(pEven t);
switch(addressE vent)
{
case ADDRESS_EVENT.A E_RINGING:
{
CurrentRingCoun t++;
break;
}
}
}
private void OnCallNotifyEve nt(ITCallNotifi cationEvent pEvent)
{
CALL_NOTIFICATI ON_EVENT callEvent = pEvent.Event;
if(Call != null)
{
Marshal.Release ComObject(Call) ;
Call = null;
}
Call = (ITBasicCallCon trol)(object)pE vent.Call;
IsNewCall = true;
Marshal.Release ComObject(pEven t);
switch(callEven t)
{
case CALL_NOTIFICATI ON_EVENT.CNE_MO NITOR:
{
break;
}
case CALL_NOTIFICATI ON_EVENT.CNE_OW NER:
{
break;
}
}
if(CallNotifica tion != null)
CallNotificatio n(this);
}
private void OnCallStateEven t(ITCallStateEv ent pEvent)
{
CALL_STATE state = pEvent.State;
Marshal.Release ComObject(pEven t);
if(CallState != null)
CallState(this, state);
switch(state)
{
case CALL_STATE.CS_I DLE:
{
break;
}
case CALL_STATE.CS_I NPROGRESS:
{
break;
}
case CALL_STATE.CS_O FFERING:
{
break;
}
case CALL_STATE.CS_C ONNECTED:
{
break;
}
case CALL_STATE.CS_Q UEUED:
{
break;
}
case CALL_STATE.CS_H OLD:
{
break;
}
case CALL_STATE.CS_D ISCONNECTED:
{
CurrentRingCoun t = 0;
DisconnectTheCa ll();
ReleaseTheCall( );
IsNewCall = false;
break;
}
}
}
private void DisconnectTheCa ll()
{
Call.Disconnect (DISCONNECT_COD E.DC_NORMAL);
}
private void ReleaseTheCall( )
{
Marshal.Release ComObject(Call) ;
Call = null;
}
}
}
works fine for the first call. Unfortunately, all subsequent calls are
completely ignored by TAPI until I restart the app again.
I remember running into this same problem with my original C++ code and
it was being caused by my failure to release all call related tapi
resources. As a point of reference the C++ app has been running quite
well for over a year.
Anyway, I beleive I'm releasing all the tapi interfaces when I'm done
with them but nothing I've done has solved the problem. I'm at a
complete loss as to what might be causing the problem. Any thoughts
would be greatly appreciated.
Here's the code:
=============== =========
using System;
using System.Drawing;
using System.Collecti ons;
using System.Componen tModel;
using System.Windows. Forms;
using System.Runtime. InteropServices ;
using TAPI3Lib;
namespace CallManager
{
/// <summary>
/// Summary description for TapiMsgWindow.
/// </summary>
public class TapiMsgWindow : System.Windows. Forms.Form
{
public delegate void TapiInitializat ionDelegate(obj ect sender, bool
success);
public event TapiInitializat ionDelegate TapiInitializat ion;
public delegate void CallNotificatio nDelegate(objec t sender);
public event CallNotificatio nDelegate CallNotificatio n;
public delegate void CallStateDelega te(object sender,
TAPI3Lib.CALL_S TATE callState);
public event CallStateDelega te CallState;
public delegate void CallInfoDelegat e(object sender,
CALLINFOCHANGE_ CAUSE cic);
public event CallInfoDelegat e CallInfo;
public delegate void CallerIDEventDe legate(object sender,
CallerIDInfo cidInfo);
public event CallerIDEventDe legate CallerIDEvent;
public enum MEDIATYPE
{
MediaAudio = 8,
MediaModem = 16,
MediaFax = 32,
MediaVideo = 32768,
}
private MainForm _ParentForm = null;
private TAPI3Lib.TAPICl ass _TAPI = null;
private ITAddress ListenAddress = null;
private ITBasicCallCont rol Call = null;
private int RegEventsResult = -1;
private int mediaTypes = 0;
private bool IsNewCall = false;
private int CurrentRingCoun t = 0;
/// <summary>
/// Required designer variable.
/// </summary>
private System.Componen tModel.Containe r components = null;
public TapiMsgWindow()
{
InitializeCompo nent();
}
public TapiMsgWindow(M ainForm parentForm) : this()
{
_ParentForm = parentForm;
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Disp ose();
_TAPI.Unregiste rNotifications( RegEventsResult );
_TAPI.Shutdown( );
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeCompo nent()
{
this.components = new System.Componen tModel.Containe r();
this.Size = new System.Drawing. Size(300,300);
this.Text = "TapiMsgWindow" ;
}
#endregion
public bool InitTAPI()
{
bool result = false;
_TAPI = new TAPI3Lib.TAPICl ass();
try
{
_TAPI.Initializ e();
_TAPI.Event += new
ITTAPIDispatchE ventNotificatio n_EventEventHan dler(OnTapiEven t);
result = SelectAddress() ;
}
catch(Exception ex)
{
MessageBox.Show (ex.Message);
result = false;
}
if(TapiInitiali zation != null)
TapiInitializat ion(this, result);
return result;
}
private bool SelectAddress()
{
bool result = false;
ITCollection addresses = (ITCollection)_ TAPI.Addresses;
ITAddress curAddress = null;
ListenAddress = null;
//Careful here. The array is 1 based NOT 0 based;
for(int i = 1; i <= addresses.Count ; i++)
{
curAddress = (ITAddress)addr esses[i];
if(curAddress.S tate == ADDRESS_STATE.A S_INSERVICE)
{
ITMediaSupport mediaSupport = (ITMediaSupport )curAddress;
// Get the supported media types...
mediaTypes = mediaSupport.Me diaTypes;
mediaSupport = null;
if((mediaTypes & (int)MEDIATYPE. MediaAudio) ==
(int)MEDIATYPE. MediaAudio)
{
ListenAddress = curAddress;
break;
}
}
}
// Did we find the address we were looking for?
if(ListenAddres s != null)
{
RegEventsResult = _TAPI.RegisterC allNotification s(ListenAddress ,
true, true, mediaTypes, 1);
_TAPI.EventFilt er = (int)(
TAPI_EVENT.TE_C ALLNOTIFICATION |
TAPI_EVENT.TE_C ALLSTATE |
TAPI_EVENT.TE_D IGITEVENT |
TAPI_EVENT.TE_C ALLINFOCHANGE |
TAPI_EVENT.TE_A DDRESS
);
}
else
{
MessageBox.Show ("No TAPI address selected");
result = false;
}
result = true;
return result;
}
private void OnTapiEvent(TAP I_EVENT TapiEvent, object pEvent)
{
switch(TapiEven t)
{
case TAPI_EVENT.TE_C ALLSTATE:
{
OnCallStateEven t((ITCallStateE vent)pEvent);
break;
}
case TAPI_EVENT.TE_A DDRESS:
{
OnAddressEvent( (ITAddressEvent )pEvent);
break;
}
case TAPI_EVENT.TE_C ALLNOTIFICATION :
{
OnCallNotifyEve nt((ITCallNotif icationEvent)pE vent);
break;
}
case TAPI_EVENT.TE_C ALLINFOCHANGE:
{
OnCallInfoEvent ((ITCallInfoCha ngeEvent)pEvent );
break;
}
case TAPI_EVENT.TE_P HONEEVENT:
{
Marshal.Release ComObject(pEven t);
break;
}
case TAPI_EVENT.TE_D IGITEVENT:
{
OnDigitEvent((I TDigitDetection Event)pEvent);
break;
}
case TAPI_EVENT.TE_G ATHERDIGITS:
{
OnGatherDigits( (ITDigitsGather edEvent)pEvent) ;
break;
}
case TAPI_EVENT.TE_C ALLMEDIA:
{
OnCallMediaChan ged((ITCallMedi aEvent)pEvent);
break;
}
case TAPI_EVENT.TE_T ONEEVENT:
{
OnCallToneEvent ((ITToneDetecti onEvent)pEvent) ;
break;
}
default:
{
Marshal.Release ComObject(pEven t);
break;
}
}
}
private void OnCallInfoEvent (ITCallInfoChan geEvent pEvent)
{
Console.WriteLi ne("CallInfoEve nt:");
Console.WriteLi ne(pEvent.Cause .ToString());
if(CallInfo != null)
CallInfo(this, pEvent.Cause);
try
{
if(pEvent.Cause == CALLINFOCHANGE_ CAUSE.CIC_CALLE RID)
{
if(CurrentRingC ount >= 2)
{
string callerIDName =
pEvent.Call.get _CallInfoString (CALLINFO_STRIN G.CIS_CALLERIDN AME);
string callerIDNumber =
pEvent.Call.get _CallInfoString (CALLINFO_STRIN G.CIS_CALLERIDN UMBER);
CallerIDInfo cidInfo = new CallerIDInfo(ca llerIDNumber,
callerIDName);
if(CallerIDEven t != null)
CallerIDEvent(t his, cidInfo);
}
}
}
catch(Exception ex)
{
MessageBox.Show (string.Format( "CallInfoEv ent failed with the
following exception:{0}", ex.Message));
}
finally
{
Marshal.Release ComObject(pEven t);
}
}
private void OnDigitEvent(IT DigitDetectionE vent pEvent)
{
try
{
byte digit = pEvent.Digit;
int digitMode = pEvent.DigitMod e;
}
finally
{
Marshal.Release ComObject(pEven t);
}
}
private void OnGatherDigits( ITDigitsGathere dEvent pEvent)
{
try
{
}
finally
{
Marshal.Release ComObject(pEven t);
}
}
private void OnCallMediaChan ged(ITCallMedia Event pEvent)
{
try
{
}
finally
{
Marshal.Release ComObject(pEven t);
}
}
private void OnCallToneEvent (ITToneDetectio nEvent pEvent)
{
try
{
}
finally
{
Marshal.Release ComObject(pEven t);
}
}
private void OnAddressEvent( ITAddressEvent pEvent)
{
ADDRESS_EVENT addressEvent = pEvent.Event;
Marshal.Release ComObject(pEven t);
switch(addressE vent)
{
case ADDRESS_EVENT.A E_RINGING:
{
CurrentRingCoun t++;
break;
}
}
}
private void OnCallNotifyEve nt(ITCallNotifi cationEvent pEvent)
{
CALL_NOTIFICATI ON_EVENT callEvent = pEvent.Event;
if(Call != null)
{
Marshal.Release ComObject(Call) ;
Call = null;
}
Call = (ITBasicCallCon trol)(object)pE vent.Call;
IsNewCall = true;
Marshal.Release ComObject(pEven t);
switch(callEven t)
{
case CALL_NOTIFICATI ON_EVENT.CNE_MO NITOR:
{
break;
}
case CALL_NOTIFICATI ON_EVENT.CNE_OW NER:
{
break;
}
}
if(CallNotifica tion != null)
CallNotificatio n(this);
}
private void OnCallStateEven t(ITCallStateEv ent pEvent)
{
CALL_STATE state = pEvent.State;
Marshal.Release ComObject(pEven t);
if(CallState != null)
CallState(this, state);
switch(state)
{
case CALL_STATE.CS_I DLE:
{
break;
}
case CALL_STATE.CS_I NPROGRESS:
{
break;
}
case CALL_STATE.CS_O FFERING:
{
break;
}
case CALL_STATE.CS_C ONNECTED:
{
break;
}
case CALL_STATE.CS_Q UEUED:
{
break;
}
case CALL_STATE.CS_H OLD:
{
break;
}
case CALL_STATE.CS_D ISCONNECTED:
{
CurrentRingCoun t = 0;
DisconnectTheCa ll();
ReleaseTheCall( );
IsNewCall = false;
break;
}
}
}
private void DisconnectTheCa ll()
{
Call.Disconnect (DISCONNECT_COD E.DC_NORMAL);
}
private void ReleaseTheCall( )
{
Marshal.Release ComObject(Call) ;
Call = null;
}
}
}
Comment