0

最后一行抛出的异常告诉我,我正在尝试在受保护的内存上读/写。我在这里做错了什么?谢谢

   int count = (int)WinApi.SendMessage(_chatHwnd, WinApi.LB_GETCOUNT, 0, 0);
    Debug.WriteLine("count=" + count);
    StringBuilder sb = new StringBuilder(count * 20);

    for (int i = _lastReadPosition; i < count; i++) {
        int len = (int)WinApi.SendMessage(_chatHwnd, WinApi.LB_GETTEXTLEN, i, 0);

        IntPtr text = Marshal.AllocHGlobal(len);
        byte[] itemText = new byte[len];

        WinApi.SendMessage(_chatHwnd, WinApi.LB_GETTEXT, i, text.ToInt32());
        Marshal.Copy(text, itemText, 0, len);

        string s = System.Text.Encoding.UTF8.GetString(itemText);
        sb.Append(s);
    }
    Debug.WriteLine("analise"); <- EXCEPTION THROWN HERE
4

1 回答 1

1

来自 msdn:

LB_GETTEXTLEN

返回值是字符串的长度,以 TCHAR 为单位,不包括终止空字符。在某些条件下,这个值实际上可能大于文本的长度。有关详细信息,请参阅以下备注部分。

LB_GETTEXT

指向将接收字符串的缓冲区的指针;它是 LPTSTR 类型,随后被转换为 LPARAM。缓冲区必须为字符串和终止空字符提供足够的空间。可以在 LB_GETTEXT 消息之前发送 LB_GETTEXTLEN 消息以检索字符串的长度(以 TCHAR 为单位)。

您需要为一个额外的空 TCHAR 提供空间。但是,我在您的代码中看到了其他几个问题:

  • 你的系统是WinNT?然后 lb_gettextlen 返回 TCHAR 中的长度,在 NT 系统上,一个 TCHAR 是两个字节长
  • 我看到 AllocHGlobal,但我没有看到 FreeHGlobal。内存泄漏?
  • 为什么使用 UTF8 编码将字节数组转换为字符串?您需要使用 Unicode。
  • 您的 SendMessage 接口有潜在危险,因为它不需要 x64 指针。

更新:通常您的代码必须如下所示:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, 
    [MarshalAs(UnmanagedType.LPTStr)] StringBuilder lParam);

private void Form1_Shown(object sender, EventArgs e)
{
    int count = (int)SendMessage(_chatHwnd, WinApi.LB_GETCOUNT, IntPtr.Zero, IntPtr.Zero);
    StringBuilder sb = new StringBuilder(count * 20);

    for (int i = _lastReadPosition; i < count; i++)
    {
        int len = (int)SendMessage(_chatHwnd, WinApi.LB_GETTEXTLEN, (IntPtr)i, IntPtr.Zero);
        StringBuilder LineBuilder = new StringBuilder(len + 1);
        SendMessage(_chatHwnd, WinApi.LB_GETTEXT, (IntPtr)i, LineBuilder);
        sb.Append(LineBuilder.ToString());
    }
}
于 2009-06-29T06:38:17.193 回答