GetWindowText()抛出错误而不被try/catch捕获

Nei*_*l_M 4 c# exception-handling try-catch user32

当我为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) }
Run Code Online (Sandbox Code Playgroud)

我有两个问题:

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

  2. 任何想法,除了使用try/catch之外,当它遇到这种类型的错误时我怎么能阻止程序崩溃

干杯

Mik*_*ray 9

1.

有些例外是无法捕获的.一种类型是StackOverflow或OutOfMemory,因为实际上没有内存可供分配给运行的处理程序.另一种类型是通过Windows OS传送到CLR的类型.此机制称为结构化异常处理.这些异常可能非常糟糕,因为CLR无法确定其自身的内部状态是否一致,有时称为损坏的状态异常.在.Net 4中,托管代码默认不处理这些异常.

上面的消息来自AccessViolationException,这是一种损坏的状态异常.发生这种情况是因为您正在调用一个非托管方法,该方法正在写入缓冲区的末尾.请参见文章可能处理这些异常.

2.

这里的示例代码是否有效?您需要确保非托管代码不会写入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();
}
Run Code Online (Sandbox Code Playgroud)