これは、WPF SplashScreen クラスのバグです。.NET 4.6 では、BitmapHandle は SafeHandle クラスであり、そのReleaseHandle()メソッドは次のようになります。
protected override bool ReleaseHandle()
{
return UnsafeNativeMethods.DeleteObject(handle);
}
これは非常に正しいです。何が起こっても、GDI ビットマップ オブジェクトが適切に破棄されることが保証されます。バグはSplashScreen.DestroyResources()メソッドに存在し、非常に役立ちます。
private void DestroyResources()
{
//...
if (_hBitmap != null && !_hBitmap.IsClosed)
{
UnsafeNativeMethods.DeleteObject(_hBitmap.MakeHandleRef(null).Handle);
_hBitmap.Close();
_hBitmap = null;
}
//...
}
への 2 回の呼び出しDeleteObject
、1 回が多すぎます。デバッガーには、このようなバグを監視する MDA (Managed Debugging Assistant) があり、ReleaseHandle() が失敗してステップインするのを確認します。MDA はデフォルトでオフになっているため (賢明ではありません)、通常これは表示されません。デバッグ > 例外 > マネージ デバッグ アシスタント > ReleaseHandleFailed. 通知の受信を停止するには、チェックを外します。
このようなバグは非常に厄介で、リサイクル攻撃を処理するための扉を開きます。ただし、実際に悪用される可能性は非常に低く、Close() 呼び出しは DeleteObject() 呼び出しの直後に続き、ビットマップは特に危険ではありません :) 技術的には事故が発生する可能性があります。別のスレッドで同時に GDI オブジェクトを作成する必要があります。これは、WPF アプリではあまり発生しません。
connect.microsoft.com でバグを報告できます。この Q+A へのリンクで十分です。