2009-06-29 8 views
0

Mir wird durch eine Ausnahme, die in der letzten Zeile, die ich versuche zu lesen/schreiben auf geschützten Speicher geschrieben werden, erzählt. Was mache ich hier falsch? DankLesen/Schreiben auf geschützten Speicherausnahme ausgelöst (. Net)

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 

Antwort

1

Vom Msdn:

LB_GETTEXTLEN

Der Rückgabewert ist die Länge der Zeichenfolge, in TCHARs, ohne das abschließende Nullzeichen. Unter bestimmten Bedingungen kann dieser Wert tatsächlich größer als die Länge des Textes sein. Weitere Informationen finden Sie im folgenden Abschnitt "Hinweise".

LB_GETTEXT

Ein Zeiger auf den Puffer, der den String empfangen wird; Es ist der Typ LPTSTR, der anschließend in eine LPARAM umgewandelt wird. Der Puffer muss über genügend Speicherplatz für die Zeichenfolge und ein abschließendes Nullzeichen verfügen. Eine Nachricht LB_GETTEXTLEN kann vor der Nachricht LB_GETTEXT gesendet werden, um die Länge der Zeichenfolge in TCHARs abzurufen.

Sie müssen Platz für eine zusätzliche null TCHAR bieten. Allerdings sehe ich mehrere andere Probleme in Ihrem Code:

  • Ihr System ist WinNT? Dann gibt lb_gettextlen Länge in TCHAR und auf NT-Systemen ein TCHAR ist zwei Bytes lang
  • Ich sehe AllocHGlobal, aber ich sehe nicht FreeHGlobal. Speicherleck?
  • Warum konvertieren Sie Byte-Array in Zeichenfolge mit UTF8-Codierung? Sie müssen Unicode verwenden.
  • Ihr SendMessage-Interface ist potenziell gefährlich, da es keine x64-Zeiger erwartet.

Update: Im Allgemeinen Ihr Code wie folgt aussehen muss:

[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()); 
    } 
} 
Verwandte Themen