LineMakeCall在七月三月的ATAPI抛出ObjectDisposedException

本文关键字:ATAPI 抛出 ObjectDisposedException 三月 在七月 LineMakeCall | 更新日期: 2023-09-27 18:07:50

我目前正在使用JulMar的ATAPI与微软的电话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的建议做的

尝试将int 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;
}

LineMakeCall在七月三月的ATAPI抛出ObjectDisposedException

如果你查看函数的MSDN页面,你可以注意到这个部分:

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

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

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

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

尝试以下步骤:

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