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

文字列を受け取るバッファーへのポインター。後で LPARAM にキャストされるのは LPTSTR 型です。バッファには、文字列と終端のヌル文字のための十分なスペースが必要です。LB_GETTEXTLEN メッセージを LB_GETTEXT メッセージの前に送信して、文字列の長さ (TCHAR) を取得できます。

1 つの追加のヌル TCHAR 用のスペースを提供する必要があります。ただし、コードには他にもいくつかの問題があります。

  • お使いのシステムは WinNT ですか? 次に、lb_gettextlen は長さを TCHAR で返します。NT システムでは、1 つの TCHAR の長さが 2 バイトです。
  • AllocHGlobal は表示されますが、FreeHGlobal は表示されません。メモリーリーク?
  • UTF8エンコーディングを使用してバイト配列を文字列に変換するのはなぜですか? ユニコードを使用する必要があります。
  • 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 に答える