I'm tring to catch Correupted state exceptions, (CES) in my WPF app. I simply want to log the error before exiting. My app uses legacy Win32/COM dlls hence the need to catch these. My code to catch these is below. (I've added the HandleProcessCorruptedStateExceptions in a few places because it doesn't work in the handler itself). The snippet that generates the crash is below the handler. However I'm still seeing the System error dialog and my handers never fire... Any help appreciated
public partial class App : Application
{
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
AppDomain.CurrentDomain.FirstChanceException += new EventHandler<FirstChanceExceptionEventArgs>(CurrentDomain_FirstChanceException);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
}
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
EatIt();
}
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
EatIt();
}
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
void CurrentDomain_FirstChanceException(object sender, FirstChanceExceptionEventArgs e)
{
EatIt();
}
private void EatIt()
{
// Add some kind of logging then terminate...
}
}
Snippet that generates a crash
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
CrashIt();
}
unsafe static void CrashIt()
{
var obj = new byte[1];
var pin = GCHandle.Alloc(obj, GCHandleType.Pinned);
byte* p = (byte*)pin.AddrOfPinnedObject();
for (int ix = 0; ix < 256开发者_高级运维; ++ix) *p-- = 0;
GC.Collect();
}
}
I've modified the startup code to enclosed the application with a try/catch clause. Still no success. Does anyone actually know how to get this stuff to work???. (I still get the Windows error dialog)
public class EntryPoint
{
// All WPF applications should execute on a single-threaded apartment (STA) thread
[STAThread]
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
public static void Main()
{
CustomApplication app = new CustomApplication();
try
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
app.Run();
}
catch (Exception)
{
System.Diagnostics.Debug.WriteLine("xx");
}
}
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
System.Diagnostics.Debug.WriteLine("xx");
}
}
public class CustomApplication : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
MainWindow window = new MainWindow();
window.Show();
}
}
Reading the section on corrupted state exceptions it seems to me that the method which actually does the try..catch needs the attribute to be applied. You are registering handlers for some events, hence your attributes have no effect.
Reading some more it seems that the behaviour changed between .NET 3.5 and 4.0 so you may want to try something out as written on that article
What may work is writing an entry point yourself andf starting the WPF app with Initialize/Run, then mark the entry point method and write a try/catch around the run.
Since .NET 6 there is no support for corrupted process recovery and HandleProcessCorruptedStateExceptions attribute is ignored.
From the SYSLIB0032 warning documentation:
Recovery from corrupted process state exceptions is not supported, and the HandleProcessCorruptedStateExceptionsAttribute type is marked as obsolete, starting in .NET 6. Using this API in code generates warning SYSLIB0032 at compile time.
精彩评论