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) }

2 つの質問があります。

  1. try catch でエラーがキャッチされないのはなぜですか?

  2. try/catchを使用する以外に、このタイプのエラーが発生したときにプログラムのクラッシュを停止する方法を教えてください

乾杯

4

2 に答える 2

9

1.

キャッチできない例外がいくつかあります。1 つのタイプは StackOverflow または OutOfMemory です。これは、ハンドラーを実行するために割り当てるメモリが文字どおりないためです。もう 1 つのタイプは、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();
}
于 2012-06-01T16:02:59.073 に答える
2

GetWindowTextに提供しているパラメーターが原因で、これらの外部メソッドを呼び出すと問題が発生する可能性があります。次のことを試してみるべきだと思います。

try{
    int strLength = NativeMethods.GetWindowTextLength(wndHandle);
    var wndStr = new StringBuilder(strLength + 1);
    GetWindowText(wndHandle, wndStr, wndStr.Capacity);
   }
catch(Exception e){ LogError(e) }
于 2012-06-01T15:58:49.733 に答える