Entwickler-Ecke

C# - Die Sprache - TAPI Problem beim Annehmen eines Anrufes


ichbinfrodo - Mo 22.01.07 23:41
Titel: TAPI Problem beim Annehmen eines Anrufes
Hallo,

ich verwende diesen http://www.codeproject.com/cs/internet/devangpro.asp Code um ankommende Anrufe per TAPI zu signalisieren.
Ausgehende Gespräche lassen sich problemlos aufbauen. Bei eingehenden Gesprächen wird eine Meldung ausgegeben, dass jemand anrufen will. Wenn ich jedoch einen Anruf annehmen will, kommt es zu einer Fehlermeldung, nämlich dass die im folgenden markierete Typumwandlung nicht erlaubt ist:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
    private void button3_Click(object sender, System.EventArgs e)
    {
      IEnumCall ec = ia[line].EnumerateCalls();
      uint arg=0;
      ITCallInfo ici;
      try
      {
        ec.Next(1,out ici,ref arg);


                                [b]// genau hier tritt der Fehler auf!![/b]
        ITBasicCallControl bc=(TAPI3Lib.ITBasicCallControl)ici;



        if(!reject)
        {
          bc.Answer();
        }
        else
        {
          bc.Disconnect(DISCONNECT_CODE.DC_REJECTED);
          ici.ReleaseUserUserInfo();
        }
      }
      catch(Exception exp)
      {
        MessageBox.Show("There may not be any calls to answer! \n\n"+exp.ToString(),"TAPI3");
      }
    }


Das gleiche Problem habe ich, wenn ich einen Anruf ablehnen oder weiterleiten will.
Falls sich also jemand in Sachen TAPI auskennt und mir sagen kann was falsch ist oder jemand eine alternative Möglichkeit kennt, einen Anruf anzunehmen, bitte melden :)

Grüße

Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt


jasocul - Di 23.01.07 09:08

Ich glaube nicht, dass das ein TAPI-Problem ist. Hast Du Dir schon mal angeschaut, welchen Inhalt "ici" hat? Vielleicht ist es leer (null/nil)? In dem Fall solltest Du Dir mal die Methode ec.Next genauer ansehen.


ichbinfrodo - Di 23.01.07 10:05

Nun, "ici" ist nicht null.
Wenn ich die den Befehl "ici.get_CallInfoString(CALLINFO_STRING.CIS_CALLERIDNUMBER)" wie unten angegeben einfüge, so wird auch die richtige Nummer des Anrufenden ausgegeben.



C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
...
ec.Next(1,out ici,ref arg);

// Nummer des Anrufenden asgeben
MessageBox.Show("Nummer: " + ici.get_CallInfoString(CALLINFO_STRING.CIS_CALLERIDNUMBER));

// genau hier tritt der Fehler auf!![/b]
ITBasicCallControl bc=(TAPI3Lib.ITBasicCallControl)ici;
...


Moderiert von user profile iconjasocul: C#-Tags hinzugefügt


jasocul - Di 23.01.07 10:17

Ich habe mir jetzt nicht die Sourcen runtergeladen (habe im Moment nur eine .NET 2.0-Umgebung). Daher solltest Du folgendes noch beachten, bzw. prüfen:
Du kannst eine Typumwandlung, wie hier von Dir vorgesehen, nur machen, wenn die Umwandlung in eine Vorgänger-Klasse erfolgt. Das soll heißen, dass ITBasicCallControl ein Vorgänger von ITCallInfo sein muss.
Ich bin immer noch ziemlich sicher, dass das Problem nichts mit TAPI zu tun. Unter Win32 habe ich da schon einiges mit gemacht.


ichbinfrodo - Di 23.01.07 10:48

Das mit den Klassen werde ich noch prüfen.
Wie werden Anrufe denn sonst im allgemeinen mit TAPI angenommen?


jasocul - Di 23.01.07 11:21

Dafür benutze ich spezielle Komponenten [http://tapi.delphiclub.de/]. Aber wie gesagt unter Win32 und nicht in .NET.
Ich müsste auch erst in den Sourcen nachsehen, wie die API-Aufrufe genau aussehen.


ichbinfrodo - Di 23.01.07 20:09

Vielen Dank für die bisherigen Antworten. Leider hat sich an meinem Problem nichts geändert.
Falls jemand ein wenig Zeit hat und sich den Code anschauen würde, wäre ich sehr dankbar!
Link: http://www.codeproject.com/cs/internet/devangpro.asp


ichbinfrodo - Mi 24.01.07 11:26

Nun habe ich folgende Seite gefunden:

http://support.microsoft.com/default.aspx?scid=kb;EN-US;841712

Wie soll ich das verstehen? Kann das in diesem Beispiel-Programm also garnicht funktionieren (muss doch aber wohl)?


jasocul - Mi 24.01.07 12:09

Unmanaged Code bedeutet lediglich, dass es kein reiner .NET-Code ist, der bei TAPI3 genutzt wird.
Allerdings weiß ich jetzt nicht ganz genau, ob man mit C# überhaupt unmanaged-code verwenden kann. :gruebel:


ichbinfrodo - Mi 24.01.07 12:27

Kann es sein dass die Typumwandlung deswegen nicht funktioniert, oder hat das eine mit dem anderen nichts zu tun?


jasocul - Mi 24.01.07 13:15

Wenn ich ehrlich bin: :nixweiss:


Kha - Mi 24.01.07 13:53

Ich verstehe das Problem überhaupt nicht, wie kommst du überhaupt auf die Idee, dass sich diese beiden Klassen ineinander casten ließen :gruebel: ? Und die Erklärung für den KB-Artikel knallt einem VS sofort mit 12 Fehlermeldungen vor den Latz:
Zitat:
Warnung 1 Mindestens ein Argument für ITCallInfo.GetCallInfoBuffer kann nicht vom Laufzeitmarshaller gemarshallt werden. Diese Argumente werden deshalb als Zeiger übergeben und erfordern zum Ändern möglicherweise unsicheren Code. tapi3_dev

@jascoul: Die Konvertierung nach VS05 hat bei mir ohne Probleme funktioniert ;) . Und der Hauptteil, nämlich die Com-Typen, ist ja gar nicht im 1.1-Projekt enthalten, sondern wird von VS selbst erst erstellt.


ichbinfrodo - Mi 24.01.07 14:14

Mein Problem: Ich will mit dem oben genannten Programm Anrufe annehmen. Leider geht das wegen dem beschriebenen Fehler nicht. Ich denke, bis zu dieser einen Zeile mit dem Cast stimmt auch alles. Anrufe werden signalisiert, ich kann die nummer erfragen, nur das eigentliche annehmen des Anrufes (sind gerade mal 2 Zeilen im Quelltext) geht nicht.

Meine Frage: Warum geht das nicht und WIE kann ich den Fehler beheben?


ichbinfrodo - Do 25.01.07 19:50

Inzwischen bin ich der Meinung, dass mir die nötigen Rechte fehlen, den Anruf anzunhemen.



von MSDN:

Privilege

Privilege refers to whether an application owns or is monitoring the session. If the application owns the session, it is allowed to perform a variety of session operations. If the application is only monitoring, it will receive state messages and it can access session information, but any attempt to perform most operations will result in an error.

During initialization, an application tells TAPI which privilege level it requires on which addresses. TAPI offers incoming sessions only to applications that have registered for either owner or owner and monitor privilege.

An application's privilege on a session it creates is always owner.

TAPI 2.x: See lineGetCallStatus, dwCallPrivilege member of LINECALLSTATUS, lineSetCallPrivilege.

TAPI 3.x: See ITCallInfo::get_Privilege, ITCallInfo::get_CallInfoLong, called with the CIL_NUMBEROFOWNERS or CIL_NUMBEROFMONITORS member of CALLINFO_LONG.





In meinem Pgramm gilt aber (ici.Privilege == CALL_PRIVILEGE.CP_MONITOR), müsste aber "OWNER" sein, um den Anruf anzunehmen. Auf der MSDN-Seite konnte ich keine passende Funktion finden, die das Attribut setzt. Kann man das in C# garnicht machen?


jasocul - Do 25.01.07 21:25

Ich habe gerade meine Sourcen für mein Telefon-Programm nicht zur Verfügung, aber iirc stimmen die Informationen, die Du hast. Der Status muss tatsächlich Owner sein.

Zu den Klassen, die Du in C# nutzt, gibt es doch auch die Sourcen. Schau doch dort mal nach, wo das Privileg gesetzt wird. Wenn das vernünftig programmiert ist, wirst Du sicher feststellen können, wie und wo das eingestellt werden kann.


ichbinfrodo - Do 25.01.07 21:39

Ich kann aber nur die Funktionen nutzen, die mir über die TAPI3.dll zur Verfügung gestellt werden. Da konnte ich leider keine passende Funktion zum setzen der Variable finden. Auch in der Auflistung von der MSDN-Seite fehlt eine set-Funktion bei TAPI3:


TAPI 2.x: See lineGetCallStatus, dwCallPrivilege member of LINECALLSTATUS, lineSetCallPrivilege.

TAPI 3.x: See ITCallInfo::get_Privilege, ITCallInfo::get_CallInfoLong, called with the CIL_NUMBEROFOWNERS or CIL_NUMBEROFMONITORS member of CALLINFO_LONG.



War dein Projekt auch in C# mit TAPI3?
Wenn du bei Gelegenheit (am besten ganz bald :) ) in deinem Code nachschauen könntest, wie du das gelöst hast, wäre ich dir sehr dankbar!


jasocul - Fr 26.01.07 08:50

Wie weiter oben schon geschrieben, ist meine Anwendung eine Win32-Anwendung (Delphi) und nicht .NET. Es würde also nichts nützen in meinem Source nachzusehen.

Einen echten .NET-Tapi-Namespace gibt es meines Wissens noch nicht. Das was Du da hast, greift Win32-DLLs zu (Stichwort: PInvoke, iirc). Damit habe ich mich noch gar nicht beschäftigt. Wenn es bei mir zeitlich passt (und das sieht nicht besonders gut aus), werde ich mir aber am Wochenende mal die Sourcen von Deinem Link ansehen. Es muss doch möglich sein, nicht nur ein Get zu programmieren, sondern auch ein Set. Aber daran kannst Du Dich ja inzwischen schonmal versuchen. Allerdings vermute ich, dass das Casting-Problem damit nicht behoben wird.


ichbinfrodo - Fr 26.01.07 12:40

wäre schön :)


jasocul - Fr 26.01.07 13:56

Ich habs mir jetzt schonmal kurz angesehen.
Es ist tatsächlich nur ein Getter definiert. Da die TAPI3Lib nicht mit Source vorliegt, solltest Du Dich an den Programmierer wenden.

Ich habe übrigens nur einen Telefonausgang geschafft. Anrufe wurden mir nicht angezeigt. Daher konnte ich an der Stelle erstmal nicht weiter testen.

Wie oben schon gesagt: Wende Dich an der "Hersteller". Der sollte genau wissen, was da nicht funktioniert und warum es keinen Setter gibt.


ichbinfrodo - Fr 26.01.07 14:26

Die TAPI3.dll stammt von Microsoft. Erst der Treiber der hinter dieser dll in Aktion tritt stammt vom jeweiligen Geräte-Hersteller.


jasocul - Fr 26.01.07 14:47

Jo, ist klar. Ich habe ja auch von der TAPI3Lib gesprochen, in der die Funktionalität für .NET bereit gestellt wird. Übrigens ist auf der von Dir verlinkten Seite auch eine Möglichkeit Fragen zu stellen (ganz unten). Ich werde aber trotzdem noch versuchen, dem Problem auf den Grund zu kommen. Versprechen kann ich allerdings nichts.


ichbinfrodo - Fr 26.01.07 15:29

Dann bedanke ich mich schonmal für deine Bemühungen!
Leider werden die Fragen auf der verlinkten Seite nur in "sehr unregelmäßigen Abständen" beantwortet :)


Kha - Fr 26.01.07 23:57

user profile iconjasocul hat folgendes geschrieben:
Da die TAPI3Lib nicht mit Source vorliegt, solltest Du Dich an den Programmierer wenden.
Das ist doch nur der von VS automatisch generierte Wrapper :gruebel:² ...

@frodo: Der Cast sollte eigentlich unter allen Umständen schiefgehen, aber ich frage mich, warum das dem Autor und den anderen Testern nicht aufgefallen ist.


jasocul - Sa 27.01.07 00:15

@Khabarakh:
Ist mir inzwischen auch aufgefallen. Bisher habe ich unmanaged Code noch nicht verwendet. Daher meine Unerfahrenheit. Sorry.

@ichbinfrodo:
Ich werde mich trotzdem mal mit dem Problem Anrufannahme beschäftigen.


ichbinfrodo - Sa 27.01.07 09:57

Ein abgehender Anruf kann ohne Probleme über dieses Tool aufgebaut werden. Man wählt eine Nummer, die Gegenstelle nimmt ab und die Verbindung steht. Diese Verbindung kann man nun über den "Disconnect"-Button wieder trennen. Bei mir tritt da zwar auch eine Fehlermeldung auf, allerdings erst nach dem eigentlichen Trennen der Verbindung. Das Lustige an der ganzen Sache ist, dass auch dieses Trennen der Verbindung mit Hilfe von dem weiter vorne beschriebenen Cast durchgeführt wird. Und hier scheint das zu funktionieren.
Meine bisherige Erklärung dafür: Bei einem ausgehenden Anruf hat man automatisch "OWNER"-Rechte und deswegen klappt der Cast, bei einem eingehenden Anruf hat man vorerst nur das Recht "MONITOR" und muss dieses erst auf "OWNER" setzen. Dafür würde es bei TAPI2 die Funktion "lineSetCallPrivilege" geben, aber wie läuft das bei TAPI3?


ichbinfrodo - Mo 29.01.07 20:44

Na, hat keiner mehr eine Idee? :)


jasocul - Di 30.01.07 08:51

Ich konnte mich mangels Zeit nicht darum kümmern. Wird sich auch kurzfristig nicht machen lassen. Sorry.