2015-05-04 107 views
0

我試圖構建一個自定義解決方案來與我們的IP Office電話系統進行交互。我能夠找到並更新由我們的電話提供商Avaya提供的使用TAPI32.dll驅動程序的舊VB6 TAPI項目。然而,從VB6到.net的變化給我帶來了一些問題。其中最大的問題是舊代碼將一個Struct傳遞給DLL上的pinvoke函數。功能,結構和調用代碼如下所示(遺憾的長度):TAPI lineGetCallInfo返回空結果

Dim l_Call As Long       
Dim struct_MyCallInfo As lineCallInfo 
Dim l_lineGetCallInfo_Result As Long  

' Init Parameters.. 
l_Call = RMSTAPIRoutines.glhCall 

' Set Memory needed... 
struct_MyCallInfo.l_dwTotalSize = LINECALLINFO_FIXEDSIZE + LINECALLINFO_MEMSIZE 

' Run lineGetCallInfo.. 
l_lineGetCallInfo_Result = RMSTAPIDeclarations.lineGetCallInfo(l_Call, struct_MyCallInfo) 



Global Const LINECALLINFO_MEMSIZE = DEFAULT_SIZE 

Type lineCallInfo 
l_dwTotalSize As Long 
l_dwNeededSize As Long 
l_dwUsedSize As Long 

l_hLine As Long 
l_dwLineDeviceID As Long 
l_dwAddressID As Long 

l_dwBearerMode As Long 
l_dwRate As Long 
l_dwMediaMode As Long 

l_dwAppSpecific As Long 
l_dwCallID As Long 
l_dwRelatedCallID As Long 
l_dwCallParamFlags As Long 
l_dwCallStates As Long 

l_dwMonitorDigitModes As Long 
l_dwMonitorMediaModes As Long 
struct_DialParams As lineDialParams 

l_dwOrigin As Long 
l_dwReason As Long 
l_dwCompletionID As Long 
l_dwNumOwners As Long 
l_dwNumMonitors As Long 

l_dwCountryCode As Long 
l_dwTrunk As Long 

l_dwCallerIDFlags As Long 
l_dwCallerIDSize As Long 
l_dwCallerIDOffset As Long 
l_dwCallerIDNameSize As Long 
l_dwCallerIDNameOffset As Long 

l_dwCalledIDFlags As Long 
l_dwCalledIDSize As Long 
l_dwCalledIDOffset As Long 
l_dwCalledIDNameSize As Long 
l_dwCalledIDNameOffset As Long 

l_dwConnectedIDFlags As Long 
l_dwConnectedIDSize As Long 
l_dwConnectedIDOffset As Long 
l_dwConnectedIDNameSize As Long 
l_dwConnectedIDNameOffset As Long 

l_dwRedirectionIDFlags As Long 
l_dwRedirectionIDSize As Long 
l_dwRedirectionIDOffset As Long 
l_dwRedirectionIDNameSize As Long 
l_dwRedirectionIDNameOffset As Long 

l_dwRedirectingIDFlags As Long 
l_dwRedirectingIDSize As Long 
l_dwRedirectingIDOffset As Long 
l_dwRedirectingIDNameSize As Long 
l_dwRedirectingIDNameOffset As Long 

l_dwAppNameSize As Long 
l_dwAppNameOffset As Long 

l_dwDisplayableAddressSize As Long 
l_dwDisplayableAddressOffset As Long 

l_dwCalledPartySize As Long 
l_dwCalledPartyOffset As Long 

l_dwCommentSize As Long 
l_dwCommentOffset As Long 

l_dwDisplaySize As Long 
l_dwDisplayOffset As Long 

l_dwUserUserInfoSize As Long 
l_dwUserUserInfoOffset As Long 

l_dwHighLevelCompSize As Long 
l_dwHighLevelCompOffset As Long 

l_dwLowLevelCompSize As Long 
l_dwLowLevelCompOffset As Long 

l_dwChargingInfoSize As Long 
l_dwChargingInfoOffset As Long 

l_dwTerminalModesSize As Long 
l_dwTerminalModesOffset As Long 

l_dwDevSpecificSize As Long 
l_dwDevSpecificOffset As Long 

l_dwCallTreatment As Long 

l_dwCallDataSize As Long 
l_dwCallDataOffset As Long 

l_dwSendingFlowspecSize As Long 
l_dwSendingFlowspecOffset As Long 

l_dwReceivingFlowspecSize As Long 
l_dwReceivingFlowspecOffset As Long 

' >= TAPI 3.0... BEGIN 
l_dwCallerIDAddressType As Long 
l_dwCalledIDAddressType As Long 
l_dwConnectedIDAddressType As Long 
l_dwRedirectionIDAddressType As Long 
l_dwRedirectingIDAddressType As Long 
' >= TAPI 3.0... END 

mem As String * LINECALLINFO_MEMSIZE 
End Type 

Global Const LINECALLINFO_FIXEDSIZE = 344 



Declare Function lineGetCallInfo Lib "TAPI32.DLL" _ 
(ByVal l_hCall As Long, ptr_lpCallInfo As Any) As Long 

C#不會讓我這樣做(各種說法在訪問受保護的內存)。經過一番研究後,似乎每個人都同意你需要將IntPtr傳遞給非託管函數來代替Struct本身。從例子中我想出了這個代碼

struct_MyCallInfo.l_dwTotalSize = RMSTAPIDeclarations.LINECALLINFO_FIXEDSIZE + RMSTAPIDeclarations.LINECALLINFO_MEMSIZE; 

System.IntPtr sPTR = Marshal.AllocHGlobal(Marshal.SizeOf(struct_MyCallInfo)); 
Marshal.StructureToPtr(struct_MyCallInfo, sPTR, true); 

int l_lineGetCallInfo_Result = RMSTAPIEvents.lineGetCallInfo(l_Call, sPTR); 

調用這個函數

[DllImport("TAPI32.DLL", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] 
    extern public static int lineGetCallInfo(int l_hCall, System.IntPtr ptr_lpCallInfo); 

有了這個結構

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    public struct lineCallInfo 
    { 
     public int l_dwTotalSize; 
     public int l_dwNeededSize; 
     public int l_dwUsedSize; 

     public int l_hLine; 
     public int l_dwLineDeviceID; 
     public int l_dwAddressID; 

     public int l_dwBearerMode; 
     public int l_dwRate; 
     public int l_dwMediaMode; 

     public int l_dwAppSpecific; 
     public int l_dwCallID; 
     public int l_dwRelatedCallID; 
     public int l_dwCallParamFlags; 
     public int l_dwCallStates; 

     public int l_dwMonitorDigitModes; 
     public int l_dwMonitorMediaModes; 
     public lineDialParams struct_DialParams; 

     public int l_dwOrigin; 
     public int l_dwReason; 
     public int l_dwCompletionID; 
     public int l_dwNumOwners; 
     public int l_dwNumMonitors; 

     public int l_dwCountryCode; 
     public int l_dwTrunk; 

     public int l_dwCallerIDFlags; 
     public int l_dwCallerIDSize; 
     public int l_dwCallerIDOffset; 
     public int l_dwCallerIDNameSize; 
     public int l_dwCallerIDNameOffset; 

     public int l_dwCalledIDFlags; 
     public int l_dwCalledIDSize; 
     public int l_dwCalledIDOffset; 
     public int l_dwCalledIDNameSize; 
     public int l_dwCalledIDNameOffset; 

     public int l_dwConnectedIDFlags; 
     public int l_dwConnectedIDSize; 
     public int l_dwConnectedIDOffset; 
     public int l_dwConnectedIDNameSize; 
     public int l_dwConnectedIDNameOffset; 

     public int l_dwRedirectionIDFlags; 
     public int l_dwRedirectionIDSize; 
     public int l_dwRedirectionIDOffset; 
     public int l_dwRedirectionIDNameSize; 
     public int l_dwRedirectionIDNameOffset; 

     public int l_dwRedirectingIDFlags; 
     public int l_dwRedirectingIDSize; 
     public int l_dwRedirectingIDOffset; 
     public int l_dwRedirectingIDNameSize; 
     public int l_dwRedirectingIDNameOffset; 

     public int l_dwAppNameSize; 
     public int l_dwAppNameOffset; 

     public int l_dwDisplayableAddressSize; 
     public int l_dwDisplayableAddressOffset; 

     public int l_dwCalledPartySize; 
     public int l_dwCalledPartyOffset; 

     public int l_dwCommentSize; 
     public int l_dwCommentOffset; 

     public int l_dwDisplaySize; 
     public int l_dwDisplayOffset; 

     public int l_dwUserUserInfoSize; 
     public int l_dwUserUserInfoOffset; 

     public int l_dwHighLevelCompSize; 
     public int l_dwHighLevelCompOffset; 

     public int l_dwLowLevelCompSize; 
     public int l_dwLowLevelCompOffset; 

     public int l_dwChargingInfoSize; 
     public int l_dwChargingInfoOffset; 

     public int l_dwTerminalModesSize; 
     public int l_dwTerminalModesOffset; 

     public int l_dwDevSpecificSize; 
     public int l_dwDevSpecificOffset; 

     public int l_dwCallTreatment; 

     public int l_dwCallDataSize; 
     public int l_dwCallDataOffset; 

     public int l_dwSendingFlowspecSize; 
     public int l_dwSendingFlowspecOffset; 

     public int l_dwReceivingFlowspecSize; 
     public int l_dwReceivingFlowspecOffset; 

     // >= TAPI 3.0... BEGIN 
     public int l_dwCallerIDAddressType; 
     public int l_dwCalledIDAddressType; 
     public int l_dwConnectedIDAddressType; 
     public int l_dwRedirectionIDAddressType; 
     public int l_dwRedirectingIDAddressType; 
     // >= TAPI 3.0... END 

     [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 2048)]//LINEDEVSTATUS_MEMSIZE)] 
     public char[] _mem; 
     public string mem 
     { 
      get 
      { 
       return new string(_mem); 
      } 
      set 
      { 
       CopyValueToArray(_mem, value); 
      } 
     } 

     public static lineCallInfo CreateInstance() 
     { 
      lineCallInfo result = new lineCallInfo(); 
      result._mem = new char[2048]; 
      return result; 
     } 
    } 

這個工程......之類的。它返回的結果沒有拋出錯誤,但它返回的填充結構完全是空的。它應該返回指示線路類型,媒體模式,來電者信息等等的值,而不是我所有的0。

有沒有人有與TAPI託管交互的經驗?有什麼我做錯了Struct或Marshaling過程嗎?幾乎所有其他的函數調用都可以工作,其中包括我在下面做的同樣的編組。這導致我相信它可能與結構有關。

回答

0

從託管代碼封裝TAPI結構非常棘手。 TAPI將結構中的可變長度數據放入內存中,並且必須使用結構的xxxOffset和xxxSize成員來查找數據的位置。

我強烈建議使用.NET的TAPI庫,爲您完成所有那些棘手的問題。你有幾個選擇:商業AddTapi.NET或開放源碼Julmar TAPI