2012-06-04 49 views
2

我想創建一個附加到Skype與C#。我不要想使用Skype4COM,因爲我希望有消息等經驗。不幸的是,這些消息讓我感到沮喪。我有泵和這樣的設置。他們都工作,我的應用程序成功地發送「APIDiscover」消息給Skype,獲得「PendingAuth」響應,然後是「AttachSuccess」消息。但是,當我嘗試向Skype發送「ping」(應該回復「pong」)時,沒有任何反應。c#SendMessage和Skype的困境

從SendMessage函數返回代碼是但Marshall.GetLastWin32Error是(句柄無效)。使用AttachSuccess方法返回句柄。等效的C++代碼確實可行,所以我不知所措。

首先是我使用的C++代碼作爲指導: 這裏是(減少)消息泵。你可以不顧一切,但在這裏我把// < ----

static LRESULT APIENTRY SkypeAPITest_Windows_WindowProc(
HWND hWindow, UINT uiMessage, WPARAM uiParam, LPARAM ulParam) 
{ 
LRESULT lReturnCode; 
bool fIssueDefProc; 

lReturnCode=0; 
fIssueDefProc=false; 
switch(uiMessage) 
    { 
    case WM_COPYDATA: 
     if(hGlobal_SkypeAPIWindowHandle==(HWND)uiParam) 
      { 
      PCOPYDATASTRUCT poCopyData=(PCOPYDATASTRUCT)ulParam; 
      printf("Message from Skype(%u): %.*s\n", poCopyData->dwData, poCopyData->cbData, poCopyData->lpData); 
      lReturnCode=1; 
      } 
     break; 
    default: 
     if(uiMessage==uiGlobal_MsgID_SkypeControlAPIAttach) 
      { 
      switch(ulParam) 
       { 
       case SKYPECONTROLAPI_ATTACH_SUCCESS: 
        printf("!!! Connected; to terminate issue #disconnect\n"); 
        hGlobal_SkypeAPIWindowHandle=(HWND)uiParam;//<---- Right here is where we receive the handle from Skype. 
        break; 
    } 
if(fIssueDefProc) 
    lReturnCode=DefWindowProc(hWindow, uiMessage, uiParam, ulParam); 
return(lReturnCode); 
} 

,這是(再次簡單化)「發送消息」代碼

void __cdecl Global_InputProcessingThread(void *) 
{ 
static char acInputRow[1024]; 
bool fProcessed; 

if(SendMessageTimeout(HWND_BROADCAST, uiGlobal_MsgID_SkypeControlAPIDiscover, (WPARAM)hInit_MainWindowHandle, 0, SMTO_ABORTIFHUNG, 1000, NULL)!=0) 
    { 
    while(Global_Console_ReadRow(acInputRow, sizeof(acInputRow)-1)) 
     { 
     if(fProcessed==false && hGlobal_SkypeAPIWindowHandle!=NULL) 
      { 
      COPYDATASTRUCT oCopyData; 

      // send command to skype 
      oCopyData.dwData=0; 
      oCopyData.lpData=acInputRow; 
      oCopyData.cbData=strlen(acInputRow)+1; 
      if(oCopyData.cbData!=1) 
       { 
       if(SendMessage(hGlobal_SkypeAPIWindowHandle, WM_COPYDATA, (WPARAM)hInit_MainWindowHandle, (LPARAM)&oCopyData)==FALSE) 
        { 
        hGlobal_SkypeAPIWindowHandle=NULL; 
        printf("!!! Disconnected\n"); 
        } 
       } 
      } 
     } 
    } 
SendMessage(hInit_MainWindowHandle, WM_CLOSE, 0, 0); 
SetEvent(hGlobal_ThreadShutdownEvent); 
fGlobal_ThreadRunning=false; 
} 

現在這裏是我的C#

public bool PreFilterMessage(ref Message m) 
    { 
     Console.WriteLine(m.ToString()); 
     if (m.Msg == WM_COPYDATA && SkypeAPIWindowHandle == m.WParam) 
     { 
      SkypeMessage(m); 
      return true; 
     } 
     if (m.Msg == MsgApiAttach) 
     { 
      switch (m.LParam.ToInt32()) 
      { 
       case (int)SkypeControlAPIAttach.SUCCESS: 
        SkypeAPIWindowHandle = m.WParam; //Here's where we set the Skype Handle 
        AttachSuccess(m); 
        return true; 
      } 
     } 
     return false; //Defer all other messages 
    } 

這裏是我的DLL導入和發送代碼

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] 
    static extern IntPtr SendMessageA(IntPtr hWnd, UInt32 Msg, IntPtr wParam, ref MsgHelper.COPYDATASTRUCT lParam); 

    public static void Command(string c) 
    { 
     if (c.Last() != '\0') 
      c += "\0"; //Make string null terminated 
     Console.WriteLine(); 
     MsgHelper.COPYDATASTRUCT cda = new MsgHelper.COPYDATASTRUCT(); 
     cda.dwData = new IntPtr(0); 
     cda.lpData = c; 
     cda.cbData = c.Length + 1; 
     Marshal.GetLastWin32Error(); //Clear last error 
     Console.WriteLine(SendMessageA(mHelper.SkypeAPIWindowHandle, MsgHelper.WM_COPYDATA, IntPtr.Zero, ref cda)); 
     Console.WriteLine(Marshal.GetLastWin32Error()); 
    } 

COPYDATASTRUCT是:

public struct COPYDATASTRUCT 
    { 
     public IntPtr dwData; 
     public int cbData; 
     [MarshalAs(UnmanagedType.LPStr)] 
     public string lpData; 
    } 

我認爲這一切。如果我忘記了什麼,請告訴我。

任何想法,爲什麼我得到1400?

回答

0

那麼,正如我所料,它是一個小東西。 Skype API說(不要問我爲什麼)處理消息的結果必須與零(0)不同,否則Skype會認爲連接斷開。

而且,當然,消息的默認返回值是0. Skype將從最初的ApiConnectSuccess消息中獲得Zero,並立即關閉句柄。當然,當我嘗試使用手柄時,會產生1400!所以簡單設置

m.Result = new IntPtr(1); 

固定它。現在,我收到「拒絕訪問」錯誤。真好玩。

編輯:修正了 「拒絕訪問」(Win32錯誤5)通過與我的句柄來替換IntPtr.Zero:在一個

SendMessageA(mHelper.SkypeAPIWindowHandle, MsgHelper.WM_COPYDATA, mHelper.MyHandle, ref cda) 

兩個答案!