Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / Configuration / System / Configuration / Debug.cs / 1 / Debug.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Configuration { using Microsoft.Win32; using Microsoft.Win32.SafeHandles; using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Reflection; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Threading; internal static class Debug { internal const string TAG_INTERNAL = "Internal"; internal const string TAG_EXTERNAL = "External"; internal const string TAG_ALL = "*"; internal const string DATE_FORMAT = @"yyyy/MM/dd HH:mm:ss.ffff"; internal const string TIME_FORMAT = @"HH:mm:ss:ffff"; #if DBG [System.Security.SuppressUnmanagedCodeSecurityAttribute()] private static class NativeMethods { [DllImport("kernel32.dll")] internal extern static int GetCurrentProcessId(); [DllImport("kernel32.dll")] internal extern static int GetCurrentThreadId(); [DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)] internal extern static IntPtr GetCurrentProcess(); [DllImport("kernel32.dll", SetLastError=true)] internal extern static bool TerminateProcess(HandleRef processHandle, int exitCode); [DllImport("kernel32.dll", CharSet=CharSet.Auto, BestFitMapping=false)] internal extern static void OutputDebugString(string message); internal const int PM_NOREMOVE = 0x0000; internal const int PM_REMOVE = 0x0001; [StructLayout(LayoutKind.Sequential)] internal struct MSG { internal IntPtr hwnd; internal int message; internal IntPtr wParam; internal IntPtr lParam; internal int time; internal int pt_x; internal int pt_y; } [DllImport("user32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)] internal extern static bool PeekMessage([In, Out] ref MSG msg, HandleRef hwnd, int msgMin, int msgMax, int remove); internal const int MB_OK = 0x00000000, MB_OKCANCEL = 0x00000001, MB_ABORTRETRYIGNORE = 0x00000002, MB_YESNOCANCEL = 0x00000003, MB_YESNO = 0x00000004, MB_RETRYCANCEL = 0x00000005, MB_ICONHAND = 0x00000010, MB_ICONQUESTION = 0x00000020, MB_ICONEXCLAMATION = 0x00000030, MB_ICONASTERISK = 0x00000040, MB_USERICON = 0x00000080, MB_ICONWARNING = 0x00000030, MB_ICONERROR = 0x00000010, MB_ICONINFORMATION = 0x00000040, MB_DEFBUTTON1 = 0x00000000, MB_DEFBUTTON2 = 0x00000100, MB_DEFBUTTON3 = 0x00000200, MB_DEFBUTTON4 = 0x00000300, MB_APPLMODAL = 0x00000000, MB_SYSTEMMODAL = 0x00001000, MB_TASKMODAL = 0x00002000, MB_HELP = 0x00004000, MB_NOFOCUS = 0x00008000, MB_SETFOREGROUND = 0x00010000, MB_DEFAULT_DESKTOP_ONLY = 0x00020000, MB_TOPMOST = 0x00040000, MB_RIGHT = 0x00080000, MB_RTLREADING = 0x00100000, MB_SERVICE_NOTIFICATION = 0x00200000, MB_SERVICE_NOTIFICATION_NT3X = 0x00040000, MB_TYPEMASK = 0x0000000F, MB_ICONMASK = 0x000000F0, MB_DEFMASK = 0x00000F00, MB_MODEMASK = 0x00003000, MB_MISCMASK = 0x0000C000; internal const int IDOK = 1, IDCANCEL = 2, IDABORT = 3, IDRETRY = 4, IDIGNORE = 5, IDYES = 6, IDNO = 7, IDCLOSE = 8, IDHELP = 9; [DllImport("user32.dll", CharSet=CharSet.Auto, BestFitMapping=false)] internal extern static int MessageBox(HandleRef hWnd, string text, string caption, int type); internal static readonly IntPtr HKEY_LOCAL_MACHINE = unchecked((IntPtr)(int)0x80000002); internal const int READ_CONTROL = 0x00020000; internal const int STANDARD_RIGHTS_READ = READ_CONTROL; internal const int SYNCHRONIZE = 0x00100000; internal const int KEY_QUERY_VALUE = 0x0001; internal const int KEY_ENUMERATE_SUB_KEYS = 0x0008; internal const int KEY_NOTIFY = 0x0010; internal const int KEY_READ = ((STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY) & (~SYNCHRONIZE)); internal const int REG_NOTIFY_CHANGE_NAME = 1; internal const int REG_NOTIFY_CHANGE_LAST_SET = 4; [DllImport("advapi32.dll", CharSet=CharSet.Auto, BestFitMapping=false, SetLastError=true)] internal extern static int RegOpenKeyEx(IntPtr hKey, string lpSubKey, int ulOptions, int samDesired, out SafeRegistryHandle hkResult); [DllImport("advapi32.dll", ExactSpelling=true, SetLastError=true)] internal extern static int RegNotifyChangeKeyValue(SafeRegistryHandle hKey, bool watchSubTree, uint notifyFilter, SafeWaitHandle regEvent, bool async); } private class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid { // Note: Officially -1 is the recommended invalid handle value for // registry keys, but we'll also get back 0 as an invalid handle from // RegOpenKeyEx. [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode=true)] internal SafeRegistryHandle() : base(true) {} [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode=true)] internal SafeRegistryHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle) { SetHandle(preexistingHandle); } [DllImport("advapi32.dll"), SuppressUnmanagedCodeSecurity, ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private static extern int RegCloseKey(IntPtr hKey); override protected bool ReleaseHandle() { // Returns a Win32 error code, 0 for success int r = RegCloseKey(handle); return r == 0; } } private enum TagValue { Disabled = 0, Enabled = 1, Break = 2, Min = Disabled, Max = Break, } private const string TAG_ASSERT = "Assert"; private const string TAG_ASSERT_BREAK = "AssertBreak"; private const string TAG_DEBUG_VERBOSE = "DebugVerbose"; private const string TAG_DEBUG_MONITOR = "DebugMonitor"; private const string TAG_DEBUG_PREFIX = "DebugPrefix"; private const string TAG_DEBUG_THREAD_PREFIX = "DebugThreadPrefix"; private const string PRODUCT = "Microsoft .NET Framework"; private const string COMPONENT = "System.Configuration"; private static string s_regKeyName = @"Software\Microsoft\ASP.NET\Debug"; private static string s_listenKeyName = @"Software\Microsoft"; private static bool s_assert; private static bool s_assertBreak; private static bool s_includePrefix; private static bool s_includeThreadPrefix; private static bool s_monitor; private static object s_lock; private static volatile bool s_inited; private static ReadOnlyCollections_tagDefaults; private static List s_tags; private static AutoResetEvent s_notifyEvent; private static RegisteredWaitHandle s_waitHandle; private static SafeRegistryHandle s_regHandle; private static bool s_stopMonitoring; private static Hashtable s_tableAlwaysValidate; private static Type[] s_DumpArgs; private static Type[] s_ValidateArgs; private class Tag { string _name; TagValue _value; int _prefixLength; internal Tag(string name, TagValue value) { _name = name; _value = value; if (_name[_name.Length - 1] == '*') { _prefixLength = _name.Length - 1; } else { _prefixLength = -1; } } internal string Name { get {return _name;} } internal TagValue Value { get {return _value;} } internal int PrefixLength { get {return _prefixLength;} } } static Debug() { s_lock = new object(); } private static void EnsureInit() { bool continueInit = false; if (!s_inited) { lock (s_lock) { if (!s_inited) { s_tableAlwaysValidate = new Hashtable(); s_DumpArgs = new Type[1] {typeof(string)}; s_ValidateArgs = new Type[0]; List tagDefaults = new List (); tagDefaults.Add(new Tag(TAG_ALL, TagValue.Disabled)); tagDefaults.Add(new Tag(TAG_INTERNAL, TagValue.Enabled)); tagDefaults.Add(new Tag(TAG_EXTERNAL, TagValue.Enabled)); tagDefaults.Add(new Tag(TAG_ASSERT, TagValue.Break)); tagDefaults.Add(new Tag(TAG_ASSERT_BREAK, TagValue.Disabled)); tagDefaults.Add(new Tag(TAG_DEBUG_VERBOSE, TagValue.Enabled)); tagDefaults.Add(new Tag(TAG_DEBUG_MONITOR, TagValue.Enabled)); tagDefaults.Add(new Tag(TAG_DEBUG_PREFIX, TagValue.Enabled)); tagDefaults.Add(new Tag(TAG_DEBUG_THREAD_PREFIX, TagValue.Enabled)); s_tagDefaults = tagDefaults.AsReadOnly(); s_tags = new List (s_tagDefaults); GetBuiltinTagValues(); continueInit = true; s_inited = true; } } } // Work to do outside the init lock. if (continueInit) { ReadTagsFromRegistry(); Trace(TAG_DEBUG_VERBOSE, "Debugging package initialized"); // Need to read tags before starting to monitor in order to get TAG_DEBUG_MONITOR StartRegistryMonitor(); } } private static bool StringEqualsIgnoreCase(string s1, string s2) { return StringComparer.OrdinalIgnoreCase.Equals(s1, s2); } [RegistryPermission(SecurityAction.Assert, Unrestricted=true)] private static void WriteTagsToRegistry() { try { using (RegistryKey key = Registry.LocalMachine.CreateSubKey(s_regKeyName)) { List tags = s_tags; foreach (Tag tag in tags) { key.SetValue(tag.Name, tag.Value, RegistryValueKind.DWord); } } } catch { } } private static void GetBuiltinTagValues() { // Use GetTagValue instead of IsTagEnabled because it does not call EnsureInit // and potentially recurse. s_assert = (GetTagValue(TAG_ASSERT) != TagValue.Disabled); s_assertBreak = (GetTagValue(TAG_ASSERT_BREAK) != TagValue.Disabled); s_includePrefix = (GetTagValue(TAG_DEBUG_PREFIX) != TagValue.Disabled); s_includeThreadPrefix = (GetTagValue(TAG_DEBUG_THREAD_PREFIX) != TagValue.Disabled); s_monitor = (GetTagValue(TAG_DEBUG_MONITOR) != TagValue.Disabled); } [RegistryPermission(SecurityAction.Assert, Unrestricted=true)] private static void ReadTagsFromRegistry() { lock (s_lock) { try { List tags = new List (s_tagDefaults); string[] names = null; bool writeTags = false; using (RegistryKey key = Registry.LocalMachine.OpenSubKey(s_regKeyName, false)) { if (key != null) { names = key.GetValueNames(); foreach (string name in names) { TagValue value = TagValue.Disabled; try { TagValue keyvalue = (TagValue) key.GetValue(name); if (TagValue.Min <= keyvalue && keyvalue <= TagValue.Max) { value = keyvalue; } else { writeTags = true; } } catch { writeTags = true; } // Add tag to list, making sure it is unique. Tag tag = new Tag(name, (TagValue) value); bool found = false; for (int i = 0; i < s_tagDefaults.Count; i++) { if (StringEqualsIgnoreCase(name, tags[i].Name)) { found = true; tags[i] = tag; break; } } if (!found) { tags.Add(tag); } } } } s_tags = tags; GetBuiltinTagValues(); // Write tags out if there was an invalid value or // not all default tags are present. if (writeTags || (names != null && names.Length < tags.Count)) { WriteTagsToRegistry(); } } catch { s_tags = new List (s_tagDefaults); } } } private static void StartRegistryMonitor() { if (!s_monitor) { Trace(TAG_DEBUG_VERBOSE, "WARNING: Registry monitoring disabled, changes during process execution will not be recognized."); return; } Trace(TAG_DEBUG_VERBOSE, "Monitoring registry key " + s_listenKeyName + " for changes."); // Event used to notify of changes. s_notifyEvent = new AutoResetEvent(false); // Register a wait on the event. s_waitHandle = ThreadPool.RegisterWaitForSingleObject(s_notifyEvent, OnRegChangeKeyValue, null, -1, false); // Monitor the registry. MonitorRegistryForOneChange(); } private static void StopRegistryMonitor() { // Cleanup allocated handles s_stopMonitoring = true; if (s_regHandle != null) { s_regHandle.Close(); s_regHandle = null; } if (s_waitHandle != null) { s_waitHandle.Unregister(s_notifyEvent); s_waitHandle = null; } if (s_notifyEvent != null) { s_notifyEvent.Close(); s_notifyEvent = null; } Trace(TAG_DEBUG_VERBOSE, "Registry monitoring stopped."); } public static void OnRegChangeKeyValue(object state, bool timedOut) { if (!s_stopMonitoring) { if (timedOut) { StopRegistryMonitor(); } else { // Monitor again MonitorRegistryForOneChange(); // Once we're monitoring, read the changes to the registry. // We have to do this after we start monitoring in order // to catch all changes to the registry. ReadTagsFromRegistry(); } } } private static void MonitorRegistryForOneChange() { // Close the open reg handle if (s_regHandle != null) { s_regHandle.Close(); s_regHandle = null; } // Open the reg key int result = NativeMethods.RegOpenKeyEx(NativeMethods.HKEY_LOCAL_MACHINE, s_listenKeyName, 0, NativeMethods.KEY_READ, out s_regHandle); if (result != 0) { StopRegistryMonitor(); return; } // Listen for changes. result = NativeMethods.RegNotifyChangeKeyValue( s_regHandle, true, NativeMethods.REG_NOTIFY_CHANGE_NAME | NativeMethods.REG_NOTIFY_CHANGE_LAST_SET, s_notifyEvent.SafeWaitHandle, true); if (result != 0) { StopRegistryMonitor(); } } private static Tag FindMatchingTag(string name, bool exact) { List tags = s_tags; // Look for exact match first foreach (Tag tag in tags) { if (StringEqualsIgnoreCase(name, tag.Name)) { return tag; } } if (exact) { return null; } Tag longestTag = null; int longestPrefix = -1; foreach (Tag tag in tags) { if ( tag.PrefixLength > longestPrefix && 0 == string.Compare(name, 0, tag.Name, 0, tag.PrefixLength, StringComparison.OrdinalIgnoreCase)) { longestTag = tag; longestPrefix = tag.PrefixLength; } } return longestTag; } private static TagValue GetTagValue(string name) { Tag tag = FindMatchingTag(name, false); if (tag != null) { return tag.Value; } else { return TagValue.Disabled; } } private static bool TraceBreak(string tagName, string message, Exception e, bool includePrefix) { EnsureInit(); TagValue tagValue = GetTagValue(tagName); if (tagValue == TagValue.Disabled) { return false; } bool isAssert = object.ReferenceEquals(tagName, TAG_ASSERT); if (isAssert) { tagName = ""; } string exceptionMessage = null; if (e != null) { string errorCode = null; if (e is ExternalException) { errorCode = "_hr=0x" + ((ExternalException)e).ErrorCode.ToString("x", CultureInfo.InvariantCulture); } // Use e.ToString() in order to get inner exception if (errorCode != null) { exceptionMessage = "Exception " + e.ToString() + "\n" + errorCode; } else { exceptionMessage = "Exception " + e.ToString(); } } if (string.IsNullOrEmpty(message) & exceptionMessage != null) { message = exceptionMessage; exceptionMessage = null; } string traceFormat; int idThread = 0; int idProcess = 0; if (!includePrefix || !s_includePrefix) { traceFormat = "{4}\n{5}"; } else { if (s_includeThreadPrefix) { idThread = NativeMethods.GetCurrentThreadId(); idProcess = NativeMethods.GetCurrentProcessId(); traceFormat = "[0x{0:x}.{1:x} {2} {3}] {4}\n{5}"; } else { traceFormat = "[{2} {3}] {4}\n{5}"; } } string suffix = ""; if (exceptionMessage != null) { suffix += exceptionMessage + "\n"; } bool doBreak = (tagValue == TagValue.Break); if (doBreak && !isAssert) { suffix += "Breaking into debugger...\n"; } string traceMessage = string.Format(CultureInfo.InvariantCulture, traceFormat, idProcess, idThread, COMPONENT, tagName, message, suffix); NativeMethods.OutputDebugString(traceMessage); return doBreak; } private class MBResult { internal int Result; } 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. System.Diagnostics.StackFrame frame = new System.Diagnostics.StackFrame(2, true); System.Diagnostics.StackTrace trace = new System.Diagnostics.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; } #endif // // Sends the message to the debugger if the tag is enabled. // Also breaks into the debugger the value of the tag is 2 (TagValue.Break). // [System.Diagnostics.Conditional("DBG")] internal static void Trace(string tagName, string message) { #if DBG if (TraceBreak(tagName, message, null, true)) { Break(); } #endif } // // Sends the message to the debugger if the tag is enabled. // Also breaks into the debugger the value of the tag is 2 (TagValue.Break). // [System.Diagnostics.Conditional("DBG")] internal static void Trace(string tagName, string message, bool includePrefix) { #if DBG if (TraceBreak(tagName, message, null, includePrefix)) { Break(); } #endif } // // Sends the message to the debugger if the tag is enabled. // Also breaks into the debugger the value of the tag is 2 (TagValue.Break). // [System.Diagnostics.Conditional("DBG")] internal static void Trace(string tagName, string message, Exception e) { #if DBG if (TraceBreak(tagName, message, e, true)) { Break(); } #endif } // // Sends the message to the debugger if the tag is enabled. // Also breaks into the debugger the value of the tag is 2 (TagValue.Break). // [System.Diagnostics.Conditional("DBG")] internal static void Trace(string tagName, Exception e) { #if DBG if (TraceBreak(tagName, null, e, true)) { Break(); } #endif } // // Sends the message to the debugger if the tag is enabled. // Also breaks into the debugger the value of the tag is 2 (TagValue.Break). // [System.Diagnostics.Conditional("DBG")] internal static void Trace(string tagName, string message, Exception e, bool includePrefix) { #if DBG if (TraceBreak(tagName, message, e, includePrefix)) { Break(); } #endif } #if DBG #endif #if UNUSED_CODE [System.Diagnostics.Conditional("DBG")] public static void TraceException(String tagName, Exception e) { #if DBG if (TraceBreak(tagName, null, e, true)) { Break(); } #endif } #endif // // If the assertion is false and the 'Assert' tag is enabled: // * Send a message to the debugger. // * If the 'AssertBreak' tag is enabled, immediately break into the debugger // * Else display a dialog box asking the user to Abort, Retry (break), or Ignore // [System.Diagnostics.Conditional("DBG")] internal static void Assert(bool assertion, string message) { #if DBG EnsureInit(); if (assertion == false) { if (DoAssert(message)) { Break(); } } #endif } // // If the assertion is false and the 'Assert' tag is enabled: // * Send a message to the debugger. // * If the 'AssertBreak' tag is enabled, immediately break into the debugger // * Else display a dialog box asking the user to Abort, Retry (break), or Ignore // [System.Diagnostics.Conditional("DBG")] internal static void Assert(bool assertion) { #if DBG EnsureInit(); if (assertion == false) { if (DoAssert(null)) { Break(); } } #endif } // // Like Assert, but the assertion is always considered to be false. // [System.Diagnostics.Conditional("DBG")] internal static void Fail(string message) { #if DBG Assert(false, message); #endif } // // Returns true if the tag is enabled, false otherwise. // Note that the tag needn't be an exact match. // internal static bool IsTagEnabled(string tagName) { #if DBG EnsureInit(); return GetTagValue(tagName) != TagValue.Disabled; #else return false; #endif } // // Returns true if the tag present. // This function chekcs for an exact match. // internal static bool IsTagPresent(string tagName) { #if DBG EnsureInit(); return FindMatchingTag(tagName, true) != null; #else return false; #endif } // // Breaks into the debugger, or launches one if not yet attached. // [System.Diagnostics.Conditional("DBG")] internal static void Break() { #if DBG if (!System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Launch(); } else { System.Diagnostics.Debugger.Break(); } #endif } // // Tells the debug system to always validate calls for a // particular tag. This is useful for temporarily enabling // validation in stress tests or other situations where you // may not have control over the debug tags that are enabled // on a particular machine. // [System.Diagnostics.Conditional("DBG")] internal static void AlwaysValidate(string tagName) { #if DBG EnsureInit(); s_tableAlwaysValidate[tagName] = tagName; #endif } // // Throws an exception if the assertion is not valid. // Use this function from a DebugValidate method where // you would otherwise use Assert. // [System.Diagnostics.Conditional("DBG")] internal static void CheckValid(bool assertion, string message) { #if DBG if (!assertion) { throw new Exception(message); } #endif } // // Calls DebugValidate on an object if such a method exists. // // This method should be used from implementations of DebugValidate // where it is unknown whether an object has a DebugValidate method. // For example, the DoubleLink class uses it to validate the // item of type Object which it points to. // // This method should NOT be used when code wants to conditionally // validate an object and have a failed validation caught in an assert. // Use Debug.Validate(tagName, obj) for that purpose. // [System.Diagnostics.Conditional("DBG")] internal static void Validate(Object obj) { #if DBG Type type; MethodInfo mi; if (obj != null) { type = obj.GetType(); mi = type.GetMethod( "DebugValidate", BindingFlags.NonPublic | BindingFlags.Instance, null, s_ValidateArgs, null); if (mi != null) { object[] tempIndex = null; mi.Invoke(obj, tempIndex); } } #endif } // // Validates an object is the "Validate" tag is enabled, or when // the "Validate" tag is not disabled and the given 'tag' is enabled. // An Assertion is made if the validation fails. // [System.Diagnostics.Conditional("DBG")] internal static void Validate(string tagName, Object obj) { #if DBG EnsureInit(); if ( obj != null && ( IsTagEnabled("Validate") || ( !IsTagPresent("Validate") && ( s_tableAlwaysValidate[tagName] != null || IsTagEnabled(tagName))))) { try { Debug.Validate(obj); } catch (Exception e) { Debug.Assert(false, "Validate failed: " + e.InnerException.Message); } catch { Debug.Assert(false, "Validate failed. Non-CLS compliant exception caught."); } } #endif } #if DBG // // Calls DebugDescription on an object to get its description. // // This method should only be used in implementations of DebugDescription // where it is not known whether a nested objects has an implementation // of DebugDescription. For example, the double linked list class uses // GetDescription to get the description of the item it points to. // // This method should NOT be used when you want to conditionally // dump an object. Use Debug.Dump instead. // // @param obj The object to call DebugDescription on. May be null. // @param indent A prefix for each line in the description. This is used // to allow the nested display of objects within other objects. // The indent is usually a multiple of four spaces. // // @return The description. // [ReflectionPermission(SecurityAction.Assert, Unrestricted=true)] internal static string GetDescription(Object obj, string indent) { string description; Type type; MethodInfo mi; Object[] parameters; if (obj == null) { description = "\n"; } else { type = obj.GetType(); mi = type.GetMethod( "DebugDescription", BindingFlags.NonPublic | BindingFlags.Instance, null, s_DumpArgs, null); if (mi == null || mi.ReturnType != typeof(string)) { description = indent + obj.ToString(); } else { parameters = new Object[1] {(Object) indent}; description = (string) mi.Invoke(obj, parameters); } } return description; } #endif // // Dumps an object to the debugger if the "Dump" tag is enabled, // or if the "Dump" tag is not present and the 'tag' is enabled. // // @param tagName The tag to Dump with. // @param obj The object to dump. // [System.Diagnostics.Conditional("DBG")] internal static void Dump(string tagName, Object obj) { #if DBG EnsureInit(); string description; string traceTag = null; bool dumpEnabled, dumpPresent; if (obj != null) { dumpEnabled = IsTagEnabled("Dump"); dumpPresent = IsTagPresent("Dump"); if (dumpEnabled || !dumpPresent) { if (IsTagEnabled(tagName)) { traceTag = tagName; } else if (dumpEnabled) { traceTag = "Dump"; } if (traceTag != null) { description = GetDescription(obj, string.Empty); Debug.Trace(traceTag, "Dump\n" + description); } } } #endif } #if UNUSED_CODE #if DBG static internal string ToStringMaybeNull(object o) { if (o != null) { return o.ToString(); } return " "; } #endif static internal string FormatUtcDate(DateTime utcTime) { #if DBG DateTime localTime = DateTimeUtil.ConvertToLocalTime(utcTime); return localTime.ToString(DATE_FORMAT, CultureInfo.InvariantCulture); #else return string.Empty; #endif } static internal string FormatLocalDate(DateTime localTime) { #if DBG return localTime.ToString(DATE_FORMAT, CultureInfo.InvariantCulture); #else return string.Empty; #endif } #endif // UNUSED_CODE } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Configuration { using Microsoft.Win32; using Microsoft.Win32.SafeHandles; using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Reflection; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Threading; internal static class Debug { internal const string TAG_INTERNAL = "Internal"; internal const string TAG_EXTERNAL = "External"; internal const string TAG_ALL = "*"; internal const string DATE_FORMAT = @"yyyy/MM/dd HH:mm:ss.ffff"; internal const string TIME_FORMAT = @"HH:mm:ss:ffff"; #if DBG [System.Security.SuppressUnmanagedCodeSecurityAttribute()] private static class NativeMethods { [DllImport("kernel32.dll")] internal extern static int GetCurrentProcessId(); [DllImport("kernel32.dll")] internal extern static int GetCurrentThreadId(); [DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)] internal extern static IntPtr GetCurrentProcess(); [DllImport("kernel32.dll", SetLastError=true)] internal extern static bool TerminateProcess(HandleRef processHandle, int exitCode); [DllImport("kernel32.dll", CharSet=CharSet.Auto, BestFitMapping=false)] internal extern static void OutputDebugString(string message); internal const int PM_NOREMOVE = 0x0000; internal const int PM_REMOVE = 0x0001; [StructLayout(LayoutKind.Sequential)] internal struct MSG { internal IntPtr hwnd; internal int message; internal IntPtr wParam; internal IntPtr lParam; internal int time; internal int pt_x; internal int pt_y; } [DllImport("user32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto)] internal extern static bool PeekMessage([In, Out] ref MSG msg, HandleRef hwnd, int msgMin, int msgMax, int remove); internal const int MB_OK = 0x00000000, MB_OKCANCEL = 0x00000001, MB_ABORTRETRYIGNORE = 0x00000002, MB_YESNOCANCEL = 0x00000003, MB_YESNO = 0x00000004, MB_RETRYCANCEL = 0x00000005, MB_ICONHAND = 0x00000010, MB_ICONQUESTION = 0x00000020, MB_ICONEXCLAMATION = 0x00000030, MB_ICONASTERISK = 0x00000040, MB_USERICON = 0x00000080, MB_ICONWARNING = 0x00000030, MB_ICONERROR = 0x00000010, MB_ICONINFORMATION = 0x00000040, MB_DEFBUTTON1 = 0x00000000, MB_DEFBUTTON2 = 0x00000100, MB_DEFBUTTON3 = 0x00000200, MB_DEFBUTTON4 = 0x00000300, MB_APPLMODAL = 0x00000000, MB_SYSTEMMODAL = 0x00001000, MB_TASKMODAL = 0x00002000, MB_HELP = 0x00004000, MB_NOFOCUS = 0x00008000, MB_SETFOREGROUND = 0x00010000, MB_DEFAULT_DESKTOP_ONLY = 0x00020000, MB_TOPMOST = 0x00040000, MB_RIGHT = 0x00080000, MB_RTLREADING = 0x00100000, MB_SERVICE_NOTIFICATION = 0x00200000, MB_SERVICE_NOTIFICATION_NT3X = 0x00040000, MB_TYPEMASK = 0x0000000F, MB_ICONMASK = 0x000000F0, MB_DEFMASK = 0x00000F00, MB_MODEMASK = 0x00003000, MB_MISCMASK = 0x0000C000; internal const int IDOK = 1, IDCANCEL = 2, IDABORT = 3, IDRETRY = 4, IDIGNORE = 5, IDYES = 6, IDNO = 7, IDCLOSE = 8, IDHELP = 9; [DllImport("user32.dll", CharSet=CharSet.Auto, BestFitMapping=false)] internal extern static int MessageBox(HandleRef hWnd, string text, string caption, int type); internal static readonly IntPtr HKEY_LOCAL_MACHINE = unchecked((IntPtr)(int)0x80000002); internal const int READ_CONTROL = 0x00020000; internal const int STANDARD_RIGHTS_READ = READ_CONTROL; internal const int SYNCHRONIZE = 0x00100000; internal const int KEY_QUERY_VALUE = 0x0001; internal const int KEY_ENUMERATE_SUB_KEYS = 0x0008; internal const int KEY_NOTIFY = 0x0010; internal const int KEY_READ = ((STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY) & (~SYNCHRONIZE)); internal const int REG_NOTIFY_CHANGE_NAME = 1; internal const int REG_NOTIFY_CHANGE_LAST_SET = 4; [DllImport("advapi32.dll", CharSet=CharSet.Auto, BestFitMapping=false, SetLastError=true)] internal extern static int RegOpenKeyEx(IntPtr hKey, string lpSubKey, int ulOptions, int samDesired, out SafeRegistryHandle hkResult); [DllImport("advapi32.dll", ExactSpelling=true, SetLastError=true)] internal extern static int RegNotifyChangeKeyValue(SafeRegistryHandle hKey, bool watchSubTree, uint notifyFilter, SafeWaitHandle regEvent, bool async); } private class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid { // Note: Officially -1 is the recommended invalid handle value for // registry keys, but we'll also get back 0 as an invalid handle from // RegOpenKeyEx. [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode=true)] internal SafeRegistryHandle() : base(true) {} [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode=true)] internal SafeRegistryHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle) { SetHandle(preexistingHandle); } [DllImport("advapi32.dll"), SuppressUnmanagedCodeSecurity, ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] private static extern int RegCloseKey(IntPtr hKey); override protected bool ReleaseHandle() { // Returns a Win32 error code, 0 for success int r = RegCloseKey(handle); return r == 0; } } private enum TagValue { Disabled = 0, Enabled = 1, Break = 2, Min = Disabled, Max = Break, } private const string TAG_ASSERT = "Assert"; private const string TAG_ASSERT_BREAK = "AssertBreak"; private const string TAG_DEBUG_VERBOSE = "DebugVerbose"; private const string TAG_DEBUG_MONITOR = "DebugMonitor"; private const string TAG_DEBUG_PREFIX = "DebugPrefix"; private const string TAG_DEBUG_THREAD_PREFIX = "DebugThreadPrefix"; private const string PRODUCT = "Microsoft .NET Framework"; private const string COMPONENT = "System.Configuration"; private static string s_regKeyName = @"Software\Microsoft\ASP.NET\Debug"; private static string s_listenKeyName = @"Software\Microsoft"; private static bool s_assert; private static bool s_assertBreak; private static bool s_includePrefix; private static bool s_includeThreadPrefix; private static bool s_monitor; private static object s_lock; private static volatile bool s_inited; private static ReadOnlyCollections_tagDefaults; private static List s_tags; private static AutoResetEvent s_notifyEvent; private static RegisteredWaitHandle s_waitHandle; private static SafeRegistryHandle s_regHandle; private static bool s_stopMonitoring; private static Hashtable s_tableAlwaysValidate; private static Type[] s_DumpArgs; private static Type[] s_ValidateArgs; private class Tag { string _name; TagValue _value; int _prefixLength; internal Tag(string name, TagValue value) { _name = name; _value = value; if (_name[_name.Length - 1] == '*') { _prefixLength = _name.Length - 1; } else { _prefixLength = -1; } } internal string Name { get {return _name;} } internal TagValue Value { get {return _value;} } internal int PrefixLength { get {return _prefixLength;} } } static Debug() { s_lock = new object(); } private static void EnsureInit() { bool continueInit = false; if (!s_inited) { lock (s_lock) { if (!s_inited) { s_tableAlwaysValidate = new Hashtable(); s_DumpArgs = new Type[1] {typeof(string)}; s_ValidateArgs = new Type[0]; List tagDefaults = new List (); tagDefaults.Add(new Tag(TAG_ALL, TagValue.Disabled)); tagDefaults.Add(new Tag(TAG_INTERNAL, TagValue.Enabled)); tagDefaults.Add(new Tag(TAG_EXTERNAL, TagValue.Enabled)); tagDefaults.Add(new Tag(TAG_ASSERT, TagValue.Break)); tagDefaults.Add(new Tag(TAG_ASSERT_BREAK, TagValue.Disabled)); tagDefaults.Add(new Tag(TAG_DEBUG_VERBOSE, TagValue.Enabled)); tagDefaults.Add(new Tag(TAG_DEBUG_MONITOR, TagValue.Enabled)); tagDefaults.Add(new Tag(TAG_DEBUG_PREFIX, TagValue.Enabled)); tagDefaults.Add(new Tag(TAG_DEBUG_THREAD_PREFIX, TagValue.Enabled)); s_tagDefaults = tagDefaults.AsReadOnly(); s_tags = new List (s_tagDefaults); GetBuiltinTagValues(); continueInit = true; s_inited = true; } } } // Work to do outside the init lock. if (continueInit) { ReadTagsFromRegistry(); Trace(TAG_DEBUG_VERBOSE, "Debugging package initialized"); // Need to read tags before starting to monitor in order to get TAG_DEBUG_MONITOR StartRegistryMonitor(); } } private static bool StringEqualsIgnoreCase(string s1, string s2) { return StringComparer.OrdinalIgnoreCase.Equals(s1, s2); } [RegistryPermission(SecurityAction.Assert, Unrestricted=true)] private static void WriteTagsToRegistry() { try { using (RegistryKey key = Registry.LocalMachine.CreateSubKey(s_regKeyName)) { List tags = s_tags; foreach (Tag tag in tags) { key.SetValue(tag.Name, tag.Value, RegistryValueKind.DWord); } } } catch { } } private static void GetBuiltinTagValues() { // Use GetTagValue instead of IsTagEnabled because it does not call EnsureInit // and potentially recurse. s_assert = (GetTagValue(TAG_ASSERT) != TagValue.Disabled); s_assertBreak = (GetTagValue(TAG_ASSERT_BREAK) != TagValue.Disabled); s_includePrefix = (GetTagValue(TAG_DEBUG_PREFIX) != TagValue.Disabled); s_includeThreadPrefix = (GetTagValue(TAG_DEBUG_THREAD_PREFIX) != TagValue.Disabled); s_monitor = (GetTagValue(TAG_DEBUG_MONITOR) != TagValue.Disabled); } [RegistryPermission(SecurityAction.Assert, Unrestricted=true)] private static void ReadTagsFromRegistry() { lock (s_lock) { try { List tags = new List (s_tagDefaults); string[] names = null; bool writeTags = false; using (RegistryKey key = Registry.LocalMachine.OpenSubKey(s_regKeyName, false)) { if (key != null) { names = key.GetValueNames(); foreach (string name in names) { TagValue value = TagValue.Disabled; try { TagValue keyvalue = (TagValue) key.GetValue(name); if (TagValue.Min <= keyvalue && keyvalue <= TagValue.Max) { value = keyvalue; } else { writeTags = true; } } catch { writeTags = true; } // Add tag to list, making sure it is unique. Tag tag = new Tag(name, (TagValue) value); bool found = false; for (int i = 0; i < s_tagDefaults.Count; i++) { if (StringEqualsIgnoreCase(name, tags[i].Name)) { found = true; tags[i] = tag; break; } } if (!found) { tags.Add(tag); } } } } s_tags = tags; GetBuiltinTagValues(); // Write tags out if there was an invalid value or // not all default tags are present. if (writeTags || (names != null && names.Length < tags.Count)) { WriteTagsToRegistry(); } } catch { s_tags = new List (s_tagDefaults); } } } private static void StartRegistryMonitor() { if (!s_monitor) { Trace(TAG_DEBUG_VERBOSE, "WARNING: Registry monitoring disabled, changes during process execution will not be recognized."); return; } Trace(TAG_DEBUG_VERBOSE, "Monitoring registry key " + s_listenKeyName + " for changes."); // Event used to notify of changes. s_notifyEvent = new AutoResetEvent(false); // Register a wait on the event. s_waitHandle = ThreadPool.RegisterWaitForSingleObject(s_notifyEvent, OnRegChangeKeyValue, null, -1, false); // Monitor the registry. MonitorRegistryForOneChange(); } private static void StopRegistryMonitor() { // Cleanup allocated handles s_stopMonitoring = true; if (s_regHandle != null) { s_regHandle.Close(); s_regHandle = null; } if (s_waitHandle != null) { s_waitHandle.Unregister(s_notifyEvent); s_waitHandle = null; } if (s_notifyEvent != null) { s_notifyEvent.Close(); s_notifyEvent = null; } Trace(TAG_DEBUG_VERBOSE, "Registry monitoring stopped."); } public static void OnRegChangeKeyValue(object state, bool timedOut) { if (!s_stopMonitoring) { if (timedOut) { StopRegistryMonitor(); } else { // Monitor again MonitorRegistryForOneChange(); // Once we're monitoring, read the changes to the registry. // We have to do this after we start monitoring in order // to catch all changes to the registry. ReadTagsFromRegistry(); } } } private static void MonitorRegistryForOneChange() { // Close the open reg handle if (s_regHandle != null) { s_regHandle.Close(); s_regHandle = null; } // Open the reg key int result = NativeMethods.RegOpenKeyEx(NativeMethods.HKEY_LOCAL_MACHINE, s_listenKeyName, 0, NativeMethods.KEY_READ, out s_regHandle); if (result != 0) { StopRegistryMonitor(); return; } // Listen for changes. result = NativeMethods.RegNotifyChangeKeyValue( s_regHandle, true, NativeMethods.REG_NOTIFY_CHANGE_NAME | NativeMethods.REG_NOTIFY_CHANGE_LAST_SET, s_notifyEvent.SafeWaitHandle, true); if (result != 0) { StopRegistryMonitor(); } } private static Tag FindMatchingTag(string name, bool exact) { List tags = s_tags; // Look for exact match first foreach (Tag tag in tags) { if (StringEqualsIgnoreCase(name, tag.Name)) { return tag; } } if (exact) { return null; } Tag longestTag = null; int longestPrefix = -1; foreach (Tag tag in tags) { if ( tag.PrefixLength > longestPrefix && 0 == string.Compare(name, 0, tag.Name, 0, tag.PrefixLength, StringComparison.OrdinalIgnoreCase)) { longestTag = tag; longestPrefix = tag.PrefixLength; } } return longestTag; } private static TagValue GetTagValue(string name) { Tag tag = FindMatchingTag(name, false); if (tag != null) { return tag.Value; } else { return TagValue.Disabled; } } private static bool TraceBreak(string tagName, string message, Exception e, bool includePrefix) { EnsureInit(); TagValue tagValue = GetTagValue(tagName); if (tagValue == TagValue.Disabled) { return false; } bool isAssert = object.ReferenceEquals(tagName, TAG_ASSERT); if (isAssert) { tagName = ""; } string exceptionMessage = null; if (e != null) { string errorCode = null; if (e is ExternalException) { errorCode = "_hr=0x" + ((ExternalException)e).ErrorCode.ToString("x", CultureInfo.InvariantCulture); } // Use e.ToString() in order to get inner exception if (errorCode != null) { exceptionMessage = "Exception " + e.ToString() + "\n" + errorCode; } else { exceptionMessage = "Exception " + e.ToString(); } } if (string.IsNullOrEmpty(message) & exceptionMessage != null) { message = exceptionMessage; exceptionMessage = null; } string traceFormat; int idThread = 0; int idProcess = 0; if (!includePrefix || !s_includePrefix) { traceFormat = "{4}\n{5}"; } else { if (s_includeThreadPrefix) { idThread = NativeMethods.GetCurrentThreadId(); idProcess = NativeMethods.GetCurrentProcessId(); traceFormat = "[0x{0:x}.{1:x} {2} {3}] {4}\n{5}"; } else { traceFormat = "[{2} {3}] {4}\n{5}"; } } string suffix = ""; if (exceptionMessage != null) { suffix += exceptionMessage + "\n"; } bool doBreak = (tagValue == TagValue.Break); if (doBreak && !isAssert) { suffix += "Breaking into debugger...\n"; } string traceMessage = string.Format(CultureInfo.InvariantCulture, traceFormat, idProcess, idThread, COMPONENT, tagName, message, suffix); NativeMethods.OutputDebugString(traceMessage); return doBreak; } private class MBResult { internal int Result; } 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. System.Diagnostics.StackFrame frame = new System.Diagnostics.StackFrame(2, true); System.Diagnostics.StackTrace trace = new System.Diagnostics.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; } #endif // // Sends the message to the debugger if the tag is enabled. // Also breaks into the debugger the value of the tag is 2 (TagValue.Break). // [System.Diagnostics.Conditional("DBG")] internal static void Trace(string tagName, string message) { #if DBG if (TraceBreak(tagName, message, null, true)) { Break(); } #endif } // // Sends the message to the debugger if the tag is enabled. // Also breaks into the debugger the value of the tag is 2 (TagValue.Break). // [System.Diagnostics.Conditional("DBG")] internal static void Trace(string tagName, string message, bool includePrefix) { #if DBG if (TraceBreak(tagName, message, null, includePrefix)) { Break(); } #endif } // // Sends the message to the debugger if the tag is enabled. // Also breaks into the debugger the value of the tag is 2 (TagValue.Break). // [System.Diagnostics.Conditional("DBG")] internal static void Trace(string tagName, string message, Exception e) { #if DBG if (TraceBreak(tagName, message, e, true)) { Break(); } #endif } // // Sends the message to the debugger if the tag is enabled. // Also breaks into the debugger the value of the tag is 2 (TagValue.Break). // [System.Diagnostics.Conditional("DBG")] internal static void Trace(string tagName, Exception e) { #if DBG if (TraceBreak(tagName, null, e, true)) { Break(); } #endif } // // Sends the message to the debugger if the tag is enabled. // Also breaks into the debugger the value of the tag is 2 (TagValue.Break). // [System.Diagnostics.Conditional("DBG")] internal static void Trace(string tagName, string message, Exception e, bool includePrefix) { #if DBG if (TraceBreak(tagName, message, e, includePrefix)) { Break(); } #endif } #if DBG #endif #if UNUSED_CODE [System.Diagnostics.Conditional("DBG")] public static void TraceException(String tagName, Exception e) { #if DBG if (TraceBreak(tagName, null, e, true)) { Break(); } #endif } #endif // // If the assertion is false and the 'Assert' tag is enabled: // * Send a message to the debugger. // * If the 'AssertBreak' tag is enabled, immediately break into the debugger // * Else display a dialog box asking the user to Abort, Retry (break), or Ignore // [System.Diagnostics.Conditional("DBG")] internal static void Assert(bool assertion, string message) { #if DBG EnsureInit(); if (assertion == false) { if (DoAssert(message)) { Break(); } } #endif } // // If the assertion is false and the 'Assert' tag is enabled: // * Send a message to the debugger. // * If the 'AssertBreak' tag is enabled, immediately break into the debugger // * Else display a dialog box asking the user to Abort, Retry (break), or Ignore // [System.Diagnostics.Conditional("DBG")] internal static void Assert(bool assertion) { #if DBG EnsureInit(); if (assertion == false) { if (DoAssert(null)) { Break(); } } #endif } // // Like Assert, but the assertion is always considered to be false. // [System.Diagnostics.Conditional("DBG")] internal static void Fail(string message) { #if DBG Assert(false, message); #endif } // // Returns true if the tag is enabled, false otherwise. // Note that the tag needn't be an exact match. // internal static bool IsTagEnabled(string tagName) { #if DBG EnsureInit(); return GetTagValue(tagName) != TagValue.Disabled; #else return false; #endif } // // Returns true if the tag present. // This function chekcs for an exact match. // internal static bool IsTagPresent(string tagName) { #if DBG EnsureInit(); return FindMatchingTag(tagName, true) != null; #else return false; #endif } // // Breaks into the debugger, or launches one if not yet attached. // [System.Diagnostics.Conditional("DBG")] internal static void Break() { #if DBG if (!System.Diagnostics.Debugger.IsAttached) { System.Diagnostics.Debugger.Launch(); } else { System.Diagnostics.Debugger.Break(); } #endif } // // Tells the debug system to always validate calls for a // particular tag. This is useful for temporarily enabling // validation in stress tests or other situations where you // may not have control over the debug tags that are enabled // on a particular machine. // [System.Diagnostics.Conditional("DBG")] internal static void AlwaysValidate(string tagName) { #if DBG EnsureInit(); s_tableAlwaysValidate[tagName] = tagName; #endif } // // Throws an exception if the assertion is not valid. // Use this function from a DebugValidate method where // you would otherwise use Assert. // [System.Diagnostics.Conditional("DBG")] internal static void CheckValid(bool assertion, string message) { #if DBG if (!assertion) { throw new Exception(message); } #endif } // // Calls DebugValidate on an object if such a method exists. // // This method should be used from implementations of DebugValidate // where it is unknown whether an object has a DebugValidate method. // For example, the DoubleLink class uses it to validate the // item of type Object which it points to. // // This method should NOT be used when code wants to conditionally // validate an object and have a failed validation caught in an assert. // Use Debug.Validate(tagName, obj) for that purpose. // [System.Diagnostics.Conditional("DBG")] internal static void Validate(Object obj) { #if DBG Type type; MethodInfo mi; if (obj != null) { type = obj.GetType(); mi = type.GetMethod( "DebugValidate", BindingFlags.NonPublic | BindingFlags.Instance, null, s_ValidateArgs, null); if (mi != null) { object[] tempIndex = null; mi.Invoke(obj, tempIndex); } } #endif } // // Validates an object is the "Validate" tag is enabled, or when // the "Validate" tag is not disabled and the given 'tag' is enabled. // An Assertion is made if the validation fails. // [System.Diagnostics.Conditional("DBG")] internal static void Validate(string tagName, Object obj) { #if DBG EnsureInit(); if ( obj != null && ( IsTagEnabled("Validate") || ( !IsTagPresent("Validate") && ( s_tableAlwaysValidate[tagName] != null || IsTagEnabled(tagName))))) { try { Debug.Validate(obj); } catch (Exception e) { Debug.Assert(false, "Validate failed: " + e.InnerException.Message); } catch { Debug.Assert(false, "Validate failed. Non-CLS compliant exception caught."); } } #endif } #if DBG // // Calls DebugDescription on an object to get its description. // // This method should only be used in implementations of DebugDescription // where it is not known whether a nested objects has an implementation // of DebugDescription. For example, the double linked list class uses // GetDescription to get the description of the item it points to. // // This method should NOT be used when you want to conditionally // dump an object. Use Debug.Dump instead. // // @param obj The object to call DebugDescription on. May be null. // @param indent A prefix for each line in the description. This is used // to allow the nested display of objects within other objects. // The indent is usually a multiple of four spaces. // // @return The description. // [ReflectionPermission(SecurityAction.Assert, Unrestricted=true)] internal static string GetDescription(Object obj, string indent) { string description; Type type; MethodInfo mi; Object[] parameters; if (obj == null) { description = "\n"; } else { type = obj.GetType(); mi = type.GetMethod( "DebugDescription", BindingFlags.NonPublic | BindingFlags.Instance, null, s_DumpArgs, null); if (mi == null || mi.ReturnType != typeof(string)) { description = indent + obj.ToString(); } else { parameters = new Object[1] {(Object) indent}; description = (string) mi.Invoke(obj, parameters); } } return description; } #endif // // Dumps an object to the debugger if the "Dump" tag is enabled, // or if the "Dump" tag is not present and the 'tag' is enabled. // // @param tagName The tag to Dump with. // @param obj The object to dump. // [System.Diagnostics.Conditional("DBG")] internal static void Dump(string tagName, Object obj) { #if DBG EnsureInit(); string description; string traceTag = null; bool dumpEnabled, dumpPresent; if (obj != null) { dumpEnabled = IsTagEnabled("Dump"); dumpPresent = IsTagPresent("Dump"); if (dumpEnabled || !dumpPresent) { if (IsTagEnabled(tagName)) { traceTag = tagName; } else if (dumpEnabled) { traceTag = "Dump"; } if (traceTag != null) { description = GetDescription(obj, string.Empty); Debug.Trace(traceTag, "Dump\n" + description); } } } #endif } #if UNUSED_CODE #if DBG static internal string ToStringMaybeNull(object o) { if (o != null) { return o.ToString(); } return " "; } #endif static internal string FormatUtcDate(DateTime utcTime) { #if DBG DateTime localTime = DateTimeUtil.ConvertToLocalTime(utcTime); return localTime.ToString(DATE_FORMAT, CultureInfo.InvariantCulture); #else return string.Empty; #endif } static internal string FormatLocalDate(DateTime localTime) { #if DBG return localTime.ToString(DATE_FORMAT, CultureInfo.InvariantCulture); #else return string.Empty; #endif } #endif // UNUSED_CODE } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- RSAPKCS1SignatureFormatter.cs
- Helper.cs
- CodeSnippetTypeMember.cs
- Transform3DGroup.cs
- BinaryCommonClasses.cs
- WindowsPrincipal.cs
- MissingMemberException.cs
- WebBrowserEvent.cs
- EventListener.cs
- FileIOPermission.cs
- mda.cs
- ValidationErrorCollection.cs
- DrawingContextWalker.cs
- ObjectStateEntryDbDataRecord.cs
- ColorAnimationUsingKeyFrames.cs
- SpellCheck.cs
- WebScriptEnablingBehavior.cs
- CommandBinding.cs
- InternalConfigConfigurationFactory.cs
- SHA256.cs
- KernelTypeValidation.cs
- WindowsMenu.cs
- ColumnResult.cs
- BaseCAMarshaler.cs
- EastAsianLunisolarCalendar.cs
- XPathCompileException.cs
- IndexOutOfRangeException.cs
- UITypeEditor.cs
- ToolStripContentPanelRenderEventArgs.cs
- HandlerBase.cs
- InputLanguageManager.cs
- BitmapDownload.cs
- DecimalAnimationUsingKeyFrames.cs
- PropertyOverridesDialog.cs
- FormViewInsertEventArgs.cs
- CommandLineParser.cs
- VersionedStream.cs
- MissingMemberException.cs
- CachedCompositeFamily.cs
- SpellCheck.cs
- InputDevice.cs
- MimeObjectFactory.cs
- InvalidFilterCriteriaException.cs
- TreeViewAutomationPeer.cs
- ObjectSpanRewriter.cs
- WmlTextViewAdapter.cs
- Polygon.cs
- HttpRequestTraceRecord.cs
- XsltLibrary.cs
- ConfigXmlText.cs
- Accessible.cs
- WebPartCatalogCloseVerb.cs
- LambdaValue.cs
- WorkflowTransactionService.cs
- CheckableControlBaseAdapter.cs
- MimeMapping.cs
- _TimerThread.cs
- WMIGenerator.cs
- XmlAtomicValue.cs
- SQLDouble.cs
- storagemappingitemcollection.viewdictionary.cs
- SiteMapNodeCollection.cs
- IntPtr.cs
- NullableDoubleAverageAggregationOperator.cs
- ISAPIApplicationHost.cs
- SHA1.cs
- TreeView.cs
- DesignTimeParseData.cs
- VirtualPathProvider.cs
- WebPartManagerInternals.cs
- GridEntryCollection.cs
- MachineKeySection.cs
- ExpressionNormalizer.cs
- OleDbFactory.cs
- DataContractJsonSerializer.cs
- DataGridPagerStyle.cs
- GroupItemAutomationPeer.cs
- InvalidFilterCriteriaException.cs
- ComEventsSink.cs
- UpdateCommand.cs
- HebrewCalendar.cs
- RegionIterator.cs
- ListItemCollection.cs
- ShaperBuffers.cs
- Token.cs
- TypeConvertions.cs
- BitVector32.cs
- SafeArrayTypeMismatchException.cs
- dataSvcMapFileLoader.cs
- AnonymousIdentificationModule.cs
- FileInfo.cs
- SqlGatherConsumedAliases.cs
- ToolboxService.cs
- EntryPointNotFoundException.cs
- ObjectDataSourceDisposingEventArgs.cs
- MaterialGroup.cs
- _NegoStream.cs
- ParentUndoUnit.cs
- SqlUtils.cs
- WasEndpointConfigContainer.cs