2

C#を使用してSkypeへのアドオンを作成しようとしています。メッセージなどの体験をしたいので、Skype4COMは使いたくありません。残念ながら、メッセージは私をつまずかせています。私はポンプとそのようなセットアップを持っています。これらはすべて機能し、私のアプリは「APIDiscover」メッセージをSkypeに正常に送信し、「PendingAuth」応答を受け取り、次に「AttachSuccess」メッセージを受け取ります。ただし、Skypeに「ping」を送信しようとすると(「pong」と応答する必要があります)、何も起こりません。

SendMessageからの戻りコードは0ですが、Marshall.GetLastWin32Errorは1400(無効なハンドル)です。ハンドルは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を入手する理由はありますか?

4

1 に答える 1

0

さて、予想通り、小さなものでした。Skype APIによると(理由は聞かないでください)メッセージの処理結果はゼロ(0)とは異なる必要があります。そうでない場合、Skypeは接続が切断されたと見なします。

そしてもちろん、メッセージのデフォルトの戻り値は0です。Skypeは最初のApiConnectSuccessメッセージからゼロを取得し、すぐにハンドルを閉じます。もちろん、ハンドルを使おうとすると1400が発生しました!だから単に設定する

m.Result = new IntPtr(1);

修正しました。現在、「アクセスが拒否されました」というエラーが発生します。なんて楽しい。

編集:IntPtr.Zeroを私のハンドルに置き換えることで「アクセスが拒否されました」(Win32エラー5)を修正しました:

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

1つに2つの答え!

于 2012-06-04T19:24:51.107 に答える