2012-06-04 4 views
2

Я пытаюсь создать надстройку для Skype с C#. I не хотите использовать Skype4COM, так как мне бы хотелось, чтобы опыт с сообщениями и тому подобное. К сожалению, сообщения меня отключили. У меня есть насосы и такие настройки. Все они работают, и мое приложение успешно отправляет сообщение «APIDiscover» в Skype, получает ответ «PendingAuth», а затем сообщение «AttachSuccess». Однако, когда я пытаюсь отправить «пинг» на Skype (которому он должен отвечать «понг»), ничего не происходит.C# SendMessage и Skype woes

Код возврата SendMessage является но Marshall.GetLastWin32Error является (Invalid ручка). Ручка была возвращена с помощью метода 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 и сразу же закроет дескриптор. Конечно, это создало 1400, когда я попытался использовать ручку! Поэтому просто установка

m.Result = new IntPtr(1); 

исправлено. Теперь я получаю ошибку «Доступ запрещен». Как весело.

Edit: Исправлена ​​ошибка "Отказано в доступе" (Win32 ошибка 5) заменой IntPtr.Zero с моей ручкой в:

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

Два ответа в одном!