c# SendMessage 和 Skype 的困境
本文关键字:困境 Skype SendMessage | 更新日期: 2023-09-27 18:36:07
我正在尝试使用 C# 创建一个 Skype 的附加组件。我不想使用Skype4COM,因为我想要消息等体验。不幸的是,这些信息让我绊倒了。我有泵之类的设置。它们都可以工作,我的应用程序成功地将"APIDiscover"消息发送到Skype,获得"待处理身份验证"响应,然后是"AttachSuccess"消息。但是,当我尝试向Skype发送"ping"(它应该回复"pong")时,没有任何反应。
SendMessage 的返回代码为 0,但 Marshall.GetLastWin32Error 为 1400(句柄无效)。使用附加成功方法返回句柄。等效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 吗?
嗯,正如我所料,这是一件小事。Skype API 说(不要问我为什么)处理消息的结果必须不同于零 (0),否则 Skype 认为连接已断开。
当然,消息的默认返回值为 0。Skype将从最初的ApiConnectSuccess消息中获取零,并立即关闭句柄。当然,当我尝试使用手柄时,这会产生 1400!所以简单的设置
m.Result = new IntPtr(1);
修复了它。现在,我收到"访问被拒绝"错误。真好玩。
编辑:修复了"访问被拒绝"(Win32错误5),方法是将IntPtr.Zero替换为我的句柄:
SendMessageA(mHelper.SkypeAPIWindowHandle, MsgHelper.WM_COPYDATA, mHelper.MyHandle, ref cda)
两个答案合二为一!