static bool DoAssert(string message) { if (!s_assert) { return false; } // Skip 2 frames - one for this function, one for // the public Assert function that called this function. StackFrame frame = new StackFrame(2, true); StackTrace trace = new StackTrace(2, true); string fileName = frame.GetFileName(); int lineNumber = frame.GetFileLineNumber(); string traceFormat; if (!string.IsNullOrEmpty(fileName)) { traceFormat = "ASSERTION FAILED: {0}\nFile: {1}:{2}\nStack trace:\n{3}"; } else { traceFormat = "ASSERTION FAILED: {0}\nStack trace:\n{3}"; } string traceMessage = string.Format(CultureInfo.InvariantCulture, traceFormat, message, fileName, lineNumber, trace.ToString()); if (!TraceBreak(TAG_ASSERT, traceMessage, null, true)) { // If the value of "Assert" is not TagValue.Break, then don't even ask user. return false; } if (s_assertBreak) { // If "AssertBreak" is enabled, then always break. return true; } string dialogFormat; if (!string.IsNullOrEmpty(fileName)) { dialogFormat = @"Failed expression: {0} File: {1}:{2} Component: {3} PID={4} TID={5} Stack trace: {6} A=Exit process R=Debug I=Continue"; } else { dialogFormat = @"Failed expression: {0} (no file information available) Component: {3} PID={4} TID={5} Stack trace: {6} A=Exit process R=Debug I=Continue"; } string dialogMessage = string.Format( CultureInfo.InvariantCulture, dialogFormat, message, fileName, lineNumber, COMPONENT, NativeMethods.GetCurrentProcessId(), NativeMethods.GetCurrentThreadId(), trace.ToString()); MBResult mbResult = new MBResult(); Thread thread = new Thread( delegate() { for (int i = 0; i < 100; i++) { NativeMethods.MSG msg = new NativeMethods.MSG(); NativeMethods.PeekMessage(ref msg, new HandleRef(mbResult, IntPtr.Zero), 0, 0, NativeMethods.PM_REMOVE); } mbResult.Result = NativeMethods.MessageBox(new HandleRef(mbResult, IntPtr.Zero), dialogMessage, PRODUCT + " Assertion", NativeMethods.MB_SERVICE_NOTIFICATION | NativeMethods.MB_TOPMOST | NativeMethods.MB_ABORTRETRYIGNORE | NativeMethods.MB_ICONEXCLAMATION); } ); thread.Start(); thread.Join(); if (mbResult.Result == NativeMethods.IDABORT) { IntPtr currentProcess = NativeMethods.GetCurrentProcess(); NativeMethods.TerminateProcess(new HandleRef(mbResult, currentProcess), 1); } return mbResult.Result == NativeMethods.IDRETRY; }
private void WindowThreadProc() { try { Initialize(); eventWindowReady.Set(); if (windowHandle != IntPtr.Zero) { NativeMethods.MSG msg = new NativeMethods.MSG(); bool keepRunning = true; // Blocking on a GetMessage() call prevents the EE from being able to unwind // this thread properly (e.g. during AppDomainUnload). So, we use PeekMessage() // and sleep so we always block in managed code instead. // while (keepRunning) { int ret = UnsafeNativeMethods.MsgWaitForMultipleObjectsEx(0, IntPtr.Zero, 100, NativeMethods.QS_ALLINPUT, NativeMethods.MWMO_INPUTAVAILABLE); if (ret == NativeMethods.WAIT_TIMEOUT) { Thread.Sleep(1); } else { while (UnsafeNativeMethods.PeekMessage(ref msg, NativeMethods.NullHandleRef, 0, 0, NativeMethods.PM_REMOVE)) { if (msg.message == NativeMethods.WM_QUIT) { keepRunning = false; break; } UnsafeNativeMethods.TranslateMessage(ref msg); UnsafeNativeMethods.DispatchMessage(ref msg); } } } } OnShutdown(OnEventsThreadShutdownEvent); } catch (Exception e) { // In case something very very wrong happend during the creation action. // This will unblock the calling thread. // eventWindowReady.Set(); if (!((e is ThreadInterruptedException) || (e is ThreadAbortException))) { Debug.Fail("Unexpected thread exception in system events window thread proc", e.ToString()); } } Dispose(); if (eventThreadTerminated != null) { eventThreadTerminated.Set(); } }