【问题标题】:LineMakeCall in JulMar's ATAPI throws ObjectDisposedExceptionJulMar 的 ATAPI 中的 LineMakeCall 抛出 ObjectDisposedException
【发布时间】:2016-09-20 15:00:18
【问题描述】:

我目前正在使用 JulMar's ATAPI 与 Microsoft 的 Telephony API (TAPI) 2.x 进行交互。

每当我尝试向指定的线路或地址发出呼叫时,都会收到 ObjectDispoedException。我认为抛出了这个异常,因为LineMakeCall-Function 从不设置 HCALL 句柄。

DLLImport:

[DllImport("Tapi32.dll", EntryPoint = "lineMakeCallW", CharSet = CharSet.Auto)]
internal static extern int lineMakeCall(HTLINE hLine, out uint hCall, string DestAddress, int CountryCode, IntPtr lpCallParams);

函数调用:

uint hCall = 0;
int rc = NativeMethods.lineMakeCall(Line.Handle, out hCall, address, countryCode, lpCp);

现在,问题是当这个方法终止时,没有设置 hCall,我不明白为什么。但是,当我将目标框架更改为 .NET 4 或更高版本(默认情况下我在 .NET 3.5 上运行我的应用程序)时,将设置 hCall。

据我了解,out 参数必须在函数终止之前设置。

我阅读了 .NET 3.5 和 .NET 4 之间的差异,但没有发现任何对我的案例有用的东西。

有人知道为什么没有设置 out 参数吗?

编辑:

我终于设法让它工作并想分享这个解决方案。我基本上做了 Kris Vanherck 推荐的事情

尝试将 out uint hCall 的签名更改为 ref IntPtr lphCall

DLLImport:

[DllImport("Tapi32.dll", EntryPoint = "lineMakeCallW", CharSet = CharSet.Auto)]
internal static extern int lineMakeCall(HTLINE hLine, IntPtr hCall, string DestAddress, int CountryCode, IntPtr lpCallParams);

函数调用:

    public TapiCall MakeCall(string address, int countryCode, MakeCallParams param)
    {
        if (!Line.IsOpen)
            throw new TapiException("Line is not open", NativeMethods.LINEERR_OPERATIONUNAVAIL);

        IntPtr lpCp = IntPtr.Zero;
        //jf 2016-10-07
        IntPtr lpHcall = IntPtr.Zero;
        //jf
        try
        {
            lpCp = MakeCallParams.ProcessCallParams(_addressId, param, 0);

            //jf 2016-10-16
            CallHandle callHandle = new CallHandle();
            lpHcall = Marshal.AllocHGlobal(Marshal.SizeOf(callHandle));
            Marshal.StructureToPtr(callHandle, lpHcall, true);
            //jf

            int rc = NativeMethods.lineMakeCall(Line.Handle, lpHcall, address, countryCode, lpCp);
            if (rc < 0)
                throw new TapiException("lineMakeCall failed", rc);
            else
            {
                // Wait for the LINE_REPLY so we don't need to deal with the value type 
                // issues of IntPtr being filled in async.
                var req = new PendingTapiRequest(rc, null, null);
                Line.TapiManager.AddAsyncRequest(req);
                req.AsyncWaitHandle.WaitOne();
                if (req.Result < 0)
                    throw new TapiException("lineMakeCall failed", req.Result);

                //jf 2016-10-07
                Marshal.PtrToStructure(lpHcall, callHandle);
                //jf
                var call = new TapiCall(this, callHandle.hCall);
                AddCall(call);
                return call;
            }
        }
        finally
        {
            //jf 2016-10-07
            if(lpHcall != IntPtr.Zero)
                Marshal.FreeHGlobal(lpHcall);
            //jf

            if (lpCp != IntPtr.Zero)
                Marshal.FreeHGlobal(lpCp);
        }
    }

最后是 CallHandle 类:

[StructLayout(LayoutKind.Sequential)]
internal class CallHandle
{
    internal uint hCall;
}

【问题讨论】:

    标签: c# .net tapi objectdisposedexception


    【解决方案1】:

    如果您查看 MSDN page 的功能,您可以注意此部分:

    该句柄只有在应用程序收到LINE_REPLY消息表明lineMakeCall函数成功完成后才有效。

    所以不保证在函数调用结束前设置。而且它实际上不是一个手柄。从命名中可以看出:“lp”代表长指针,“h”代表句柄。 'lphCall' 是指向内存位置的指针,当 LINE_REPLY 返回时(可能在函数返回之前、期间或之后),将设置句柄。

    这是一个时间问题,改变框架可能只是让一些事情变得更慢/更快,给你不同的结果。

    尝试将out uint hCall 的签名更改为ref IntPtr lphCall

    【讨论】:

    • 感谢您的回答,但这没有帮助。 lphCall 仍未设置。
    【解决方案2】:

    尝试以下步骤:

    • 重新启动 Windows 电话服务。在某些情况下,问题是 ATAPI 是 Win32 TAPI dll 上的包装器,可以在停止/重新启动 Windows 电话服务后卸载/重新加载
    • ATAPI 位版本必须与您的操作系统版本相同。确保您在 64 位 Windows 环境中使用 64 位 ATAPI 版本,在 32 位环境中使用 32 位 ATAPI。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-18
      • 1970-01-01
      • 2015-10-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多