2017-05-03 12 views
0

J'essayais d'obtenir du texte de chaque contrôle dans la hiérarchie. Le code suivant fonctionne correctement si j'utilise la méthode unsafe. Cependant, en utilisant la version non gérée semble briser hWnd, qui se plaint résultat hWnd = GetAncestor(hWnd, GetAncestorFlags.GA_PARENT):Quel est le problème avec ce code non géré en C#?

System.AccessViolationException: « Tentative de lecture ou d'écriture de mémoire protégée. C'est souvent une indication que l'autre mémoire est corrompue.

J'ai vérifié hWnd n'a pas été changé après le retour de la fonction GetWindowTextRaw, et si je commente la deuxième SendMessage dans cette fonction ne causera pas la question (bien qu'il se clairement pas le texte de la fenêtre).

(PS: J'utilise PInvoke.User32 dans NuGet)

// using static PInvoke.User32; 

public static string GetWindowTextRaw(IntPtr hWnd) { 
    // Allocate correct string length first 
    int length = (int)SendMessage(hWnd, WindowMessage.WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero); 
    char[] buff = new char[length + 1]; 
    IntPtr iptr = Marshal.AllocHGlobal(buff.Length); 
    SendMessage(hWnd, WindowMessage.WM_GETTEXT, (IntPtr)(length + 1), iptr); 
    Marshal.Copy(iptr, buff, 0, length + 1); 
    Marshal.FreeHGlobal(iptr); 
    //unsafe 
    //{ 
    // fixed (char* p = buff) 
    //  SendMessage(hWnd, WindowMessage.WM_GETTEXT, (IntPtr)(length + 1), (IntPtr)p); 
    //} 
    return new string(buff).TrimEnd('\0'); 
} 

private void button1_Click(object sender, EventArgs { 
    POINT p; 
    IntPtr hWnd; 
    //while (true) 
    if (GetCursorPos(out p)) { 
     hWnd = WindowFromPoint(p); ; 
     Debug.Print($"{p.x} {p.y} 0x{(int)hWnd:x8}"); 
     while (hWnd != IntPtr.Zero) { 
      Debug.Print($"{GetWindowTextRaw(hWnd)}"); 
      hWnd = GetAncestor(hWnd, GetAncestorFlags.GA_PARENT); 
     } 
     Thread.Sleep(500); 
    } 
} 
+0

Vous pouvez envisager d'utiliser C++/CLI pour le code d'interopérabilité. –

+0

Copie possible de [Tentative de lecture ou d'écriture de la mémoire protégée. C'est souvent une indication que l'autre mémoire est corrompue] (http://stackoverflow.com/questions/4074585/attempted-to-read-or-write-protected-memory-this-is-often-an-indication-that- ot) – ThePerplexedOne

+0

@ Howаn Comment? Des références? Merci! –

Répondre

3
IntPtr iptr = Marshal.AllocHGlobal(buff.Length); 

mauvaise taille, vous avez besoin buff.Length * sizeof(char). Deux fois plus qu'il alloue maintenant. Comme écrit, le code corrompt le même tas que le système d'exploitation utilise, tout peut arriver ensuite. Un AVE est un résultat normal et heureux, mais pas garanti.

+0

Merci! C'est parfaitement résolu le problème! Je me concentrais sur la valeur de 'hWnd' mais je ne pensais pas que ça pouvait être un débordement! Pire encore, j'avais peu d'expérience en Marshalling, et beaucoup d'autres messages étaient des '' AllocHGlobal '' - des octets qui n'ont pas besoin de multiplicateur, donc je n'ai pas pensé à la taille. Merci beaucoup pour votre aide! –