调用SendMessage(P / Invoke)会一直崩溃

时间:2010-02-02 00:04:36

标签: c# pinvoke

我不得不写一个与第三方程序通信的应用程序(AOL,对不起。:()

做了大量的研究我发现了一些使用P/Invoke的方法,并且大多数情况下的工作没问题,但它在后续的试验中崩溃,特别是{{1 }}。我正在概述下面的崩溃代码。

所有这些都从旧的旧Visual Basic文件移植到.NET。这是古老的,我知道如果它不可行 - 我只是希望有一种比Visual Basic 4.0更好的方法来完成这项工作。

SendMessage

3 个答案:

答案 0 :(得分:2)

你正在使用Wide字节SendMessage..ie来表示宽字符,你试过普通的Sendmessage吗? public static extern int SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);

我也注意到,就像你试图根据richtextbox控件的句柄更改值,因此在另一个进程中寻找AOL的客户端窗口......这是正确的吗?

这可能是问题的根源,直接修改属于不属于您的窗口的控件(您的程序被管理,修改非托管进程的窗口)......这可以解释它崩溃的原因。你能澄清什么是十六进制常量吗?

编辑:当您使用WM_GETTEXTLENGTH和WM_GETTEXT时,它们是Windows消息的一部分,用于从控件中检索文本长度和实际文本。如果你看here并看看pinvoke.net对它们有什么看法......当你用WM_GETTEXTLENGTH和WM_GETTEXT发出'SendMessage'时,你告诉Windows - '嘿,告诉我文本的长度我在参数n中给你的相关句柄。刚发生在我身上,值得一试...我会摆脱那些SendMessage pinvokes并使用这一个..

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, StringBuilder lParam);
//If you use '[Out] StringBuilder', initialize the string builder with proper length first.

child = FindClientWindow();
room = FindChildByClass(child, "RICHCNTLREADONLY");

length = SendMessage(n, 0x000E, IntPtr.Zero, IntPtr.Zero);

StringBuilder sbBuf = new StringBuilder(length);

SendMessageByString(room, 0x000D, new IntPtr( length.ToInt32() + 1 ), out sbBuf); // this is the line that keeps crashing on me.

试试并回到这里...... :)

希望这有帮助, 最好的祝福, 汤姆。

答案 1 :(得分:0)

您是否设法解决了“尝试读取或写入受保护的内存”的问题。错误? t0mm13b's answer似乎分配了一个StringBuilder,其缓冲区是一个字符太小(以容纳尾随'\ 0')。

这里的代码对我有用:

[DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true)]
private static extern Int32 SendMessageByString(IntPtr wnd, UInt32 msg, Int32 WParam, StringBuilder output);
const int WM_GETTEXTLENGTH = 0x000e;
const int WM_GETTEXT = 0x000d;

public static string GetText(IntPtr hWnd)
{
    int len = SendMessageByString(hWnd, WM_GETTEXTLENGTH, 0, null);
    var sb = new StringBuilder(len + 1);  // +1 is for the trailing '\0'
    SendMessageByString(hWnd, WM_GETTEXT, sb.Capacity, sb);
    return sb.ToString();
}

答案 2 :(得分:0)

我在Marshal.PtrToStringUni(bf)语句中遇到崩溃,类似情况SendMessage返回“错误大小”的文本长度为WM_GETTEXTLENGTH参数(控件类为“RICHEDIT50W” ;多行文字)。

我曾尝试添加1,10,100(对文本长度查询结果)并且即使(稍后)文本长度等于第一次调用返回的内容(WM_GETTEXTLENGTH)仍然会出错

我的解决方案是:我将结果乘以2然后我修剪它。

我确实使用了Marshal.AllocHGlobal(sz)然后Marshal.Release(bf),因此内存效率没有问题。我的猜测是,对于多行文本,Marshal.AllocHGlobal(sz)即使使用精确的文本大小(+1)也没有在内存中留出足够的空间。

也许文本中的返回字符(vbCr,vbLf)需要更多的内存:我没有发现任何可以解释这个问题,但是大小加倍对我有用。