GetWindowText()抛出错误,无法被try/catch捕获

4
当我运行下面的代码获取GetWindowText时,抛出以下错误作为内部异常:
{"尝试读取或写入受保护的内存。这通常是其他内存已损坏的迹象。"}
    [DllImport("user32.dll", EntryPoint = "GetWindowTextLength", SetLastError = true)]
    internal static extern int GetWindowTextLength(IntPtr hwnd);

    [DllImport("user32.dll", EntryPoint = "GetWindowText", SetLastError = true)]
    internal static extern int GetWindowText(IntPtr hwnd, ref StringBuilder wndTxt, int MaxCount);

try{
      int strLength = NativeMethods.GetWindowTextLength(wndHandle);
      var wndStr = new StringBuilder(strLength);
      GetWindowText(wndHandle, ref wndStr, wndStr.Capacity);
   }
    catch(Exception e){ LogError(e) }

我有两个问题:

  1. 为什么try catch没有捕获到错误?

  2. 除了使用try/catch之外,有什么办法可以防止程序在遇到这种类型的错误时崩溃?

谢谢!


1
应该是catch(Exception e)而不是catch(exception e),对吗? - hatchet - done with SOverflow
是的,只是问题中的一个笔误。 - Neil_M
1
你能试试 GetWindowText(wndHandle, wndStr, wndStr.Capacity) 吗?此外,NativeMethods.GetWindowTextLength(wndHandle) 抛出异常的可能性大吗? - hatchet - done with SOverflow
1
为什么缓冲区的有效容量应该是255?请参见http://social.msdn.microsoft.com/forums/en-US/winforms/thread/d332a263-a11b-4638-b70a-468cfd195ced/。 - Roman R.
我已经按照所述更新了代码,但仍然出现相同的错误。 - Neil_M
3
尝试移除 "ref" 关键字。 - hatchet - done with SOverflow
2个回答

9

1.

有一些异常是无法捕获的。其中一种类型是StackOverflow或OutOfMemory,因为没有内存分配给处理程序运行。另一种类型是通过Windows操作系统传递给CLR的异常。这种机制称为结构化异常处理。这些类型的异常可能非常糟糕,因为CLR无法确定自己的内部状态是否一致,有时被称为损坏的状态异常。在.Net 4中,默认情况下,托管代码不处理这些异常。

上述消息来自AccessViolationException,这是一种损坏的状态异常。这是因为您调用了一个未经管理的方法,该方法正在超出缓冲区的末尾进行写入。请参见文章,了解如何处理这些异常。

2.

示例代码here能否正常工作?您需要确保未经管理的代码不会超出StringBuilder的缓冲区范围进行写入。

public static string GetText(IntPtr hWnd)
{
    // Allocate correct string length first
    int length       = GetWindowTextLength(hWnd);
    StringBuilder sb = new StringBuilder(length + 1);
    GetWindowText(hWnd, sb, sb.Capacity);
    return sb.ToString();
}

样例代码已经完美运行。不确定是因为去掉了“ref”还是添加了1到长度,但现在它完美地工作了。谢谢Mike。 - Neil_M

2

可能是因为你向GetWindowText提供的参数导致了调用这些外部方法时出现问题。我认为你应该尝试以下操作:

try{
    int strLength = NativeMethods.GetWindowTextLength(wndHandle);
    var wndStr = new StringBuilder(strLength + 1);
    GetWindowText(wndHandle, wndStr, wndStr.Capacity);
   }
catch(Exception e){ LogError(e) }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接