调用SendMessage(P/Invoke)老是崩溃我不得不写一个应用程序,与第三方程序通信(AOL,抱歉。:()做一个大量研究我发现了一些使用P/Invoke执行此操作的方法,并且在大多数情况下它工作正常,但它在后续试验中崩溃,尤其是使用SendMessage时。我在下面概述了崩溃代码。所有这些是从一个旧的、旧的VisualBasic文件移植到.NET。它很古老,我知道它是否不可行——我只希望有比VisualBasic4.0工作项目更好的方法来做到这一点。[DllImport("kernel32.dll",SetLastError=true)][返回:MarshalAs(UnmanagedType.Bool)]publicstaticexternboolCloseHandle(IntPtrhObject);[DllImport("user32.dll",SetLastError=true)]publicstaticexternIntPtrFindWindow(stringlpClassName,stringlpWindowName);[DllImport("user32.dll",SetLastError=true)]publicstaticexternIntPtrFindWindowEx(IntPtrhwndParent,IntPtrhwndChildAfter,stringlpszClass,stringlpszWindow);[DllImport("user32.dll",SetLastError=true)]publicstaticexternIntPtrFindWindowEx(IntPtrparentHandle,IntPtrchildAfter,stringclassName,IntPtrwindowTitle);[DllImport("user32.dll",CharSet=CharSet.Auto)]publicstaticexternIntPtrSendMessage(HandleRefhWnd,UInt32Msg,IntPtrwParam,IntPtrlParam);[DllImport("user32.dll",EntryPoint="SendMessageW")]publicstaticexternIntPtrSendMessageByString(HandleRefhWnd,UInt32Msg,IntPtrwParam,StringBuilderlParam);[DllImport("user32.dll",CharSet=CharSet.Unicode,EntryPoint="SendMessageW")]publicstaticexternIntPtrSendMessageByString(HandleRefhWnd,UInt32Msg,IntPtrwParam,StringlParam);publicIntPtrFindClientWindow(){IntPtraol=IntPtr.Zero;IntPtrmdi=IntPtr.Zero;IntPtrchild=IntPtr.Zero;IntPtrrich=IntPtr.Zero;IntPtraollist=IntPtr.Zero;IntPtraolicon=IntPtr.Zero;IntPtraolstatic=IntPtr.Zero;aol=Invoke.FindWindow("AOLFrame25",null);mdi=Invoke.FindWindowEx(aol,IntPtr.Zero,"MDIClient",null);child=Invoke.FindWindowEx(mdi,IntPtr.Zero,"AOLChild",null);rich=Invoke.FindWindowEx(child,IntPtr.Zero,"RICHCNTL",null);aollist=Invoke.FindWindowEx(child,IntPtr.Zero,"_AOL_Listbox",null);aolicon=Invoke.FindWindowEx(child,IntPtr.Zero,"_AOL_Icon",null);aolstatic=Invoke.FindWindowEx(child,IntPtr.Zero,"_AOL_Static",null);if(rich!=IntPtr.Zero&&aollist!=IntPtr.Zero&&aolicon!=IntPtr.Zero&&aolstatic!=IntPtr.Zero)返回孩子;do{child=Invoke.FindWindowEx(mdi,child,"AOLChild",null);rich=Invoke.FindWindowEx(child,IntPtr.Zero,"RICHCNTL",null);aollist=Invoke.FindWindowEx(child,IntPtr.Zero,"_AOL_Listbox",null);aolicon=Invoke.FindWindowEx(child,IntPtr.Zero,"_AOL_Icon",null);aolstatic=Invoke.FindWindowEx(child,IntPtr.Zero,"_AOL_Static",null);if(rich!=IntPtr.Zero&&aollist!=IntPtr.Zero&&aolicon!=IntPtr.Zero&&aolstatic!=IntPtr.Zero)返回孩子;}while(child!=IntPtr.Zero);归还孩子;}IntPtrroom=IntPtr.Zero;IntPtrchild=IntPtr.Zero;IntPtrlength=IntPtr.Zero;IntPtrroomHandle=IntPtr.Zero;孩子=FindClientWindow();room=FindChildByClass(child,"RICHCNTLREADONLY");HandleRefn=newHandleRef(IntPtr.Zero,room);length=SendMessage(n,0x000E,IntPtr.Zero,IntPtr.Zero);//这是让我崩溃的那一行。SendMessageByString(n,0x000D,新IntPtr(length.ToInt32()+1),str);publicIntPtrFindChildByClass(IntPtrparent,stringchild){returnInvoke.FindWindowEx(parent,IntPtr.Zero,child,null);您正在使用宽字节SendMessage。.ie广角字符,你试过正常的Sendmessage..publicstaticexternintSendMessage(IntPtrhWnd,UInt32Msg,Int32wParam,Int32lParam);我还注意到您似乎正试图根据richtextbox控件的句柄更改值,因此在另一个进程中寻找AOL的客户端窗口...这是正确的吗?这可能是问题的根源,直接修改属于不属于您的窗口的控件(您的程序是托管的,修改非托管进程的窗口)......这可以解释为什么它会崩溃你能阐明什么是十六进制常数?编辑:当您使用WM_GETTEXTLENGTH和WM_GETTEXT时,它们是Windows消息的一部分,用于从控件中检索文本长度和实际文本。如果你看看这里,看看pinvoke.net对它们有什么看法......当你使用WM_GETTEXTLENGTH和WM_GETTEXT发出“SendMessage”时,你告诉Windows-'嘿,告诉我相关句柄中文本的长度我已经为您在参数n中给出。刚刚发生在我身上,值得一试......我会摆脱那些SendMessagepinvokes并使用这个......[DllImport("user32.dll",CharSet=CharSet.Auto)]staticexternIntPtrSendMessage(IntPtrhWnd,UInt32Msg,IntPtrwParam,StringBuilderlParam);//如果使用'[Out]StringBuilder',首先用适当的长度初始化字符串生成器。孩子=FindClientWindow();room=FindChildByClass(child,"RICHCNTLREADONLY");length=SendMessage(n,0x000E,IntPtr.Zero,IntPtr.Zero);StringBuildersbBuf=newStringBuilder(长度);SendMessageByString(room,0x000D,newIntPtr(length.ToInt32()+1),outsbBuf);//这是让我崩溃的那一行。试试看,回到这里...?希望这有帮助,最好的问候,汤姆。您是否设法解决了“试图读取或写入受保护的内存”的问题。错误?t0mm13b的答案似乎分配了一个StringBuilder,其缓冲区太小了一个字符(无法容纳尾随的“0”)。这是对我有用的代码:[DllImport("user32.dll",EntryPoint="SendMessage",SetLastError=true)]privatestaticexternInt32SendMessageByString(IntPtrwnd,UInt32msg,Int32WParam,StringBuilderoutput);constintWM_GETTEXTLENGTH=0x000e;constintWM_GETTEXT=0x000d;publicstaticstringGetText(IntPtrhWnd){intlen=SendMessageByString(hWnd,WM_GETTEXTLENGTH,0,null);varsb=newStringBuilder(len+1);//+1用于尾随的''SendMessageByString(hWnd,WM_GETTEXT,sb.Capacity,sb);返回sb.ToString();我在Marshal.PtrToStringUni(bf)语句中遇到类似的崩溃,其中SendMessage返回文本长度“错误大小”(控制类是“RICHEDIT50W”;多行文本)。我尝试添加1,10,100(文本长度查询结果),即使(稍后)文本长度等于第一次调用返回的长度(WM_GETTEXTLENGTH),我仍然收到错误消息。我的解决方案是:我将结果乘以2,然后修剪它。我确实使用Marshal.AllocHGlobal(sz),然后使用Marshal.Release(bf),因此内存效率没有问题。我的猜测是,对于多行文本,Marshal.AllocHGlobal(sz)没有足够的内存空间,即使是精确的文本大小(+1)。也许文本中返回的字符(vbCr、vbLf)需要更多内存:我没有找到任何可以解释这一点的东西,但加倍大小对我有用。以上是C#学习教程:调用SendMessage(P/Invoke)会一直闪退所有分享的内容。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场,如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处:
