TAPI Schnittstelle Cisco-Telefon

  • VB.NET
  • .NET (FX) 4.0

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von arnesson.

    TAPI Schnittstelle Cisco-Telefon

    Hallo Zusammen,

    ich möchte unsere Cisco-Telefonanlage nutzen, um aus einem Programm heraus den Wählvorgang auszulösen.
    Hierzu habe ich mich in etwa diesem Script bedient: Tapi3 ... Mal wieder ärger mit Events

    Wir nutzen ein Programm, dass "Proffessional Client" heißt. Wenn hier eine Telefonnummer gewählt wird, klingelt das Telefon, man nimmt ab und es wählt raus. Von eingehenden Anrufen rede ich erstmal gar nicht.

    Es scheint alles zu funktionieren, aber es tut sich am Telefon nichts.

    Erbitte Hilfe.

    Hier das modifizierte Programm:
    (Hinweis: Das 'Dim m_TAPI As New TAPIClass' musste ich ersetzten durch 'Dim m_Tapi As New TAPI3Lib.TAPI', da sonst ein Fehler auftrat)

    Visual Basic-Quellcode

    1. Imports TAPI3Lib
    2. Public Class Form1
    3. Public Const MediaAudio As Integer = 8
    4. Public Const MediaModem As Integer = 16
    5. Public Const MediaFax As Integer = 32
    6. Public Const MediaVideo As Integer = 32768
    7. Public WithEvents oTAPI As TAPI3Lib.TAPI
    8. Public oAddress As ITAddress ' will hold our selected address (you can hold many address in an array)
    9. Public RegCookie As Integer
    10. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    11. Dim m_Tapi As New TAPI3Lib.TAPI ' creating a new instance to first initialize TAPI befor attaching the events
    12. Dim MediaTypes As Integer ' a variable to hold supported media types for the address
    13. m_Tapi.Initialize() ' initializing TAPI
    14. oTAPI = m_Tapi
    15. 'oTAPI = m_TAPI ' attaching event sink
    16. m_Tapi = Nothing
    17. Dim AddressCollection As ITCollection = oTAPI.Addresses()
    18. For Each Address As ITAddress In AddressCollection ' looping through address collection
    19. If Address.State = ADDRESS_STATE.AS_INSERVICE Then ' checking if address is working
    20. Dim MediaSupport As ITMediaSupport = Address ' extracting meida support interface from the address
    21. MediaTypes = MediaSupport.MediaTypes ' extracting media types supporting
    22. MediaSupport = Nothing ' dispose of the object
    23. If MediaTypes And MediaModem = MediaModem Then ' the address is a data Modem
    24. If MediaTypes And MediaAudio = MediaAudio Then 'the address supports Audio
    25. If MsgBox(Address.AddressName, vbYesNo, "Adresse:") = MsgBoxResult.Yes Then ' EDITIERT: AUSWAHL DES DIENSTES
    26. oAddress = Address ' select this address
    27. MsgBox("we have selected this address: " + oAddress.AddressName) ' show the selected address name
    28. Exit For
    29. End If
    30. End If
    31. End If
    32. End If
    33. Next Address
    34. If Not oAddress Is Nothing Then
    35. ' registering notifications for the selected address
    36. RegCookie = oTAPI.RegisterCallNotifications(oAddress, True, False, MediaTypes, 1)
    37. oTAPI.EventFilter = TAPI_EVENT.TE_CALLNOTIFICATION Or TAPI_EVENT.TE_CALLSTATE Or TAPI_EVENT.TE_CALLINFOCHANGE 'Gibt an auf welche Events Tapi reagieren soll
    38. Else
    39. MsgBox("no address selected")
    40. End If
    41. End Sub
    42. Private Sub oTAPI_Event(ByVal TapiEvent As TAPI3Lib.TAPI_EVENT, ByVal pEvent As Object) Handles oTAPI.Event
    43. Select Case TapiEvent
    44. Case TAPI_EVENT.TE_CALLNOTIFICATION
    45. MsgBox("oTAPI_Event+ Callnotification")
    46. Case TAPI_EVENT.TE_CALLSTATE 'Funktioniert, wird ausgelöst, bei newcall.Connect(False)
    47. MsgBox("oTAPI_Event + Callstate")
    48. Case TAPI_EVENT.TE_CALLINFOCHANGE
    49. MsgBox("oTAPI_Event + Callinfochange")
    50. End Select
    51. End Sub
    52. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    53. Dim PhoneNumber As String = "015256458XXX"
    54. Dim lAddressType As Long = TAPI3Lib.TapiConstants.LINEADDRESSTYPE_PHONENUMBER
    55. Dim newcall As TAPI3Lib.ITBasicCallControl
    56. newcall = oAddress.CreateCall(PhoneNumber, TAPI3Lib.TapiConstants.LINEADDRESSTYPE_PHONENUMBER, TAPI3Lib.TapiConstants.TAPIMEDIATYPE_AUDIO)
    57. newcall.Connect(False)
    58. End Sub
    59. End Class
    Hallo,

    das ist immer noch halber VB6-Code. So wird das nix. Ich habe mal den RCW mit dem aktuellen SDK generiert. Das geht so:

    1. VS-Eingabeaufforderung starten
    2. tapi3.dll aus C:\Windows\system32 auf den Desktop kopieren (WICHTIG - Der Import ersetzt die Datei ohne Rückfrage, wenn man nicht aufpasst! Das scheitert heutzutage zum Glück an UAC)
    3. Kommandozeile: tlbimp /out:tapi3rcw.dll /machine:X64 tapi3.dll
    4. Im Projekt einen Verweis auf die generierte Datei setzen

    Mangels eines passenden Telefoniegeräts auf meinem System kann ich den RCW leider nicht richtig testen. Ich habe den Code zum Starten eines Anrufs trotzdem mal in sauberes .NET (Konsolenanwendung) übersetzt, unter Verwendung des generierten RCW. Bei mir findet das Programm natürlich kein passendes ITAddress-Objekt, sonst funktioniert der Code aber. In den Projektoptionen muss die Target-Machine auf x64-only stehen (nicht AnyCPU).

    VB.NET-Quellcode

    1. Imports tapi3rcw
    2. Imports System.Runtime.InteropServices
    3. Module Module1
    4. <System.Runtime.CompilerServices.Extension()>
    5. Public Function HasFlag(i As Integer, flag As Integer) As Boolean
    6. Return (i And flag) = flag
    7. End Function
    8. Sub Main()
    9. Dim oTapi As ITTAPI = New TAPI
    10. oTapi.Initialize()
    11. ' Implicit AddRef() on all items
    12. Dim cAddrs As ITCollection = CType(oTapi.Addresses, ITCollection)
    13. Dim addr As ITAddress
    14. Dim support As ITMediaSupport
    15. Dim addrIdx As Int32 = -1
    16. ' Iterate address collection (1-based)
    17. Dim i As Int32 = 1
    18. While addrIdx = -1 And i <= cAddrs.Count
    19. addr = CType(cAddrs.Item(i), ITAddress)
    20. If addr.State = ADDRESS_STATE.AS_INSERVICE Then
    21. support = CType(addr, ITMediaSupport) ' CType releases AddRef() of QueryInterface()
    22. If support.MediaTypes.HasFlag(TapiConstants.TAPIMEDIATYPE_DATAMODEM) Then
    23. If support.MediaTypes.HasFlag(TapiConstants.TAPIMEDIATYPE_AUDIO) Then
    24. Console.Write("Suitable address found: {0}. Use it? ", addr.AddressName)
    25. If Console.ReadLine().Equals("y") Then
    26. Console.WriteLine("Using this address.")
    27. addrIdx = i
    28. End If
    29. End If
    30. End If
    31. End If
    32. i += 1
    33. End While
    34. Dim pAddr As IntPtr
    35. ' Release unused AddRefs
    36. For i = 1 To cAddrs.Count
    37. addr = CType(cAddrs.Item(i), ITAddress)
    38. pAddr = Marshal.GetIUnknownForObject(addr) ' Get IUnknown
    39. If i <> addrIdx Then
    40. Marshal.Release(pAddr)
    41. End If
    42. Next
    43. If addrIdx = -1 Then
    44. Console.WriteLine("No address selected. Exiting.")
    45. Return
    46. End If
    47. ' This is our selected address
    48. addr = DirectCast(cAddrs.Item(addrIdx), ITAddress)
    49. pAddr = Marshal.GetIUnknownForObject(addr)
    50. ' Create a call
    51. Dim callCtrl As ITBasicCallControl = addr.CreateCall("12345", TapiConstants.LINEADDRESSTYPE_PHONENUMBER, TapiConstants.TAPIMEDIATYPE_AUDIO)
    52. callCtrl.Connect(False)
    53. Console.WriteLine("Call established.")
    54. Marshal.ReleaseComObject(callCtrl)
    55. Marshal.Release(pAddr)
    56. Marshal.ReleaseComObject(cAddrs)
    57. End Sub
    58. End Module


    Die Sache mit den Events würde ich erstmal bleiben lassen, weil du nicht weißt, ob der RCW an dieser Stelle Mist baut oder nicht. Teste erstmal den "normalen" Anruf. Du siehst ja, dass ich bereits jetzt einige COM-Referenzen rumschiebe. TLBimp kapselt für meinen Geschmack ein wenig zu viel - alles, was er nicht versteht, wird einfach Object. Das hat manchmal unerwünschte Nebenwirkungen, insbesondere bei Callbacks, wie sie ja bei Events erforderlich sind.
    Gruß
    hal2000

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „hal2000“ ()

    Servus Hal,

    danke für Deine Antwort.

    Leider kommt dabei das selbe raus wie bei meiner Version. Wieder habe ich 2 Adressen (LSI HDA Modem / HP hs2340 HSPA+ Mobile Broadband Modem) zur Verfügung.
    Bei beiden läuft es durch.
    Bei ersterem kommt ein Fenster mit "Anrufstatus", Nehmen Sie den Hörer ab und drücken Sie auf sprechen" (was nichts bringt). Aber beim zweiten kommt ganz kurz ein kleines Fenster, das fast augenblicklich wieder verschwindet, so dass ich nicht sehe, was es ist.

    Ich habe wenig Ahnung von Tapi, aber sind nicht vielleicht Tie Telefonieanbeiter (Systemsteuerung -> Telefon und Modem -> Erweitert) irgendwie relevant?
    Sagt Dir ACD irgendwas -> itwissen.info/definition/lexik…sche-Anrufverteilung.html

    Vielen Dank für Deine Hilfe!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „arnesson“ ()

    arnesson schrieb:

    Bei beiden läuft es durch.

    Das klingt doch schonmal gut.

    arnesson schrieb:

    Bei ersterem kommt ein Fenster mit "Anrufstatus", Nehmen Sie den Hörer ab und drücken Sie auf sprechen" (was nichts bringt). Aber beim zweiten kommt ganz kurz ein kleines Fenster, das fast augenblicklich wieder verschwindet, so dass ich nicht sehe, was es ist.

    Ich könnte mir vorstellen, dass du das ITBasicCallControl-Objekt aktiv halten musst. Aktuell rufst du ja callCtrl.Connect() auf, gibst das Objekt aber direkt danach wieder frei. Das bedeutet, dass auch die Systemressourcen freigegeben werden und der Anruf quasi hart abgebrochen wird. Teste mal sowas:

    VB.NET-Quellcode

    1. '[...]
    2. callCtrl.Connect(False)
    3. Console.WriteLine("Call established.")
    4. While Not Console.ReadLine().Equals("exit")
    5. End While
    6. Marshal.ReleaseComObject(callCtrl)
    7. '[...]


    arnesson schrieb:

    Ich habe wenig Ahnung von Tapi, aber sind nicht vielleicht Tie Telefonieanbeiter (Systemsteuerung -> Telefon und Modem -> Erweitert) irgendwie relevant?

    Was meinst du damit? TAPI ist ja gerade dafür da, um die Telefonie unabhängig von Anbietern und Transporttechnologie umzusetzen, ist also eine Abstraktionsschicht.

    Zu ACD: Der Link erklärt ja ganz gut, was das ist. Nur was hat das mit dem Thema zutun? Soll dein Programm später mal ACD bieten? Das müsste einfacher gehen, weil Cisco dafür bestimmt eine fertige (und vmtl. proprietäre) Lösung anbietet.

    Andere Frage: Warum benutzt ihr denn nicht den "Professional Client" weiterhin, wenn damit alles funktioniert? Und gibts das Programm irgendwo zum Download (Testversion oder ähnlich)?
    Gruß
    hal2000

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „hal2000“ ()

    hal2000 schrieb:


    Teste mal sowas:


    Das versuche ich gleich mal.

    hal2000 schrieb:


    Was meinst du damit? TAPI ist ja gerade dafür da, um die Telefonie unabhängig von Anbietern und Transporttechnologie umzusetzen, ist also eine Abstraktionsschicht.

    Das weiß ich selbst nicht so genau. Nach deiner Antwort zu schließen, macht es vermutlich keinen Sinn ;)


    hal2000 schrieb:


    Andere Frage: Warum benutzt ihr denn nicht den "Professional Client" weiterhin, wenn damit alles funktioniert? Und gibts das Programm irgendwo zum Download (Testversion oder ähnlich)?


    Weil ich direkt aus meinem Programm heraus einen Geschäftspartner anrufen möchte. Auf der Seite (vsenet.de/) habe ich keine Demo gefunden. Mit der dll habe ich auch schon herumhantiert. Um sie zu nutzten brauche ich allerdings .Net 4.5. Ich schreibe allerdings noch in Vb 2010

    arnesson schrieb:

    Auf der Seite (vsenet.de/) habe ich keine Demo gefunden.

    VSENet scheint euer Internetprovider zu sein. Keine Ahnung, ob der was mit dem Programm zutun hat - möglicherweise hat er die Software extern oder intern entwickeln lassen und verteilt diese nur an Kunden.

    Hier ist ein Überblick über TAPI: msdn.microsoft.com/en-us/libra…s733433%28v=vs.85%29.aspx

    Dein Mobilfunkmodem bringt als "Treiber" bei der Installation einen "Third Party TSP" (siehe Grafik im MSDN-Artikel) mit, der die Verbindung zwischen TAPI und dem Modem herstellt. Dadurch kannst du die "Adresse" des Modems auswählen. TAPI initiiert dann eine Verbindung, die über den TSP abgewickelt wird.

    Mir ist noch aufgefallen, dass der Connect-Aufruf so aussehen sollte:

    VB.NET-Quellcode

    1. callCtrl.Connect(True)


    Das macht den Aufruf synchron, sodass du eventuelle Fehler auch mitbekommst. False macht den Anruf asynchron, weshalb Fehlermeldungen über die (nicht registrierten) Eventhandler ankommen (d.h. eben nicht ankommen).
    Gruß
    hal2000