我目前正在使用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推荐的那个
尝试将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;
}
答案 0 :(得分:0)
如果您查看该功能的MSDN page,可以注意此部分:
句柄仅在应用程序收到指示lineMakeCall函数成功完成的LINE_REPLY消息后才有效。
因此无法保证在函数调用结束之前设置它。它实际上也不是一个句柄。你可以在命名中看到它:&#34; lp&#34;代表长指针和&#34; h&#34;处理。 &#39; lphCall&#39;是一个指向内存位置的指针,当LINE_REPLY返回时(可能在函数返回之前,期间或之后)将设置句柄。
这是一个时间问题,改变框架可能只是让一些事情变得更慢/更快,给你不同的结果。
尝试将out uint hCall
的签名更改为ref IntPtr lphCall
答案 1 :(得分:0)
请尝试以下步骤: