//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //------------------------------------------------------------------------------ /* */ #define DEBUG namespace System.Diagnostics { using System; using System.Text; using System.Reflection; using System.Collections; using System.Security.Permissions; using System.Globalization; /// /// Provides a set of properties and /// methods /// for debugging code. /// public static class Debug { #if !SILVERLIGHT /// /// Gets /// the collection of listeners that is monitoring the debug /// output. /// public static TraceListenerCollection Listeners { [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] [HostProtection(SharedState=true)] get { return TraceInternal.Listeners; } } /// /// Gets or sets a value indicating whether should be called on the /// /// after every write. /// public static bool AutoFlush { [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] get { return TraceInternal.AutoFlush; } [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] set { TraceInternal.AutoFlush = value; } } /// /// Gets or sets /// the indent level. /// public static int IndentLevel { get { return TraceInternal.IndentLevel; } set { TraceInternal.IndentLevel = value; } } /// /// Gets or sets the number of spaces in an indent. /// public static int IndentSize { get { return TraceInternal.IndentSize; } set { TraceInternal.IndentSize = value; } } /// /// Clears the output buffer, and causes buffered data to /// be written to the . /// [System.Diagnostics.Conditional("DEBUG")] public static void Flush() { TraceInternal.Flush(); } /// /// Clears the output buffer, and then closes the so that they no longer receive /// debugging output. /// [System.Diagnostics.Conditional("DEBUG")] [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] public static void Close() { TraceInternal.Close(); } /// /// Checks for a condition, and outputs the callstack if the condition is . /// [System.Diagnostics.Conditional("DEBUG")] public static void Assert(bool condition) { TraceInternal.Assert(condition); } /// /// Checks for a condition, and displays a message if the condition is /// . /// [System.Diagnostics.Conditional("DEBUG")] public static void Assert(bool condition, string message) { TraceInternal.Assert(condition, message); } /// /// Checks for a condition, and displays both the specified messages if the condition /// is . /// [System.Diagnostics.Conditional("DEBUG")] public static void Assert(bool condition, string message, string detailMessage) { TraceInternal.Assert(condition, message, detailMessage); } /// /// Checks for a condition, and displays both the specified messages if the condition /// is . /// [System.Diagnostics.Conditional("DEBUG")] public static void Assert(bool condition, string message, string detailMessageFormat, params Object[] args) { TraceInternal.Assert(condition, message, String.Format(CultureInfo.InvariantCulture, detailMessageFormat, args)); } /// /// Emits or displays a message for an assertion that always fails. /// [System.Diagnostics.Conditional("DEBUG")] public static void Fail(string message) { TraceInternal.Fail(message); } /// /// Emits or displays both messages for an assertion that always fails. /// [System.Diagnostics.Conditional("DEBUG")] public static void Fail(string message, string detailMessage) { TraceInternal.Fail(message, detailMessage); } [System.Diagnostics.Conditional("DEBUG")] public static void Print(string message) { TraceInternal.WriteLine(message); } [System.Diagnostics.Conditional("DEBUG")] public static void Print(string format, params object[] args) { TraceInternal.WriteLine(String.Format(CultureInfo.InvariantCulture, format, args)); } /// /// Writes a message to the trace listeners in the collection. /// [System.Diagnostics.Conditional("DEBUG")] public static void Write(string message) { TraceInternal.Write(message); } /// /// Writes the name of the value /// parameter to the trace listeners in the collection. /// [System.Diagnostics.Conditional("DEBUG")] public static void Write(object value) { TraceInternal.Write(value); } /// /// Writes a category name and message /// to the trace listeners in the collection. /// [System.Diagnostics.Conditional("DEBUG")] public static void Write(string message, string category) { TraceInternal.Write(message, category); } /// /// Writes a category name and the name of the value parameter to the trace /// listeners in the collection. /// [System.Diagnostics.Conditional("DEBUG")] public static void Write(object value, string category) { TraceInternal.Write(value, category); } /// /// Writes a message followed by a line terminator to the trace listeners in the /// collection. The default line terminator /// is a carriage return followed by a line feed (\r\n). /// [System.Diagnostics.Conditional("DEBUG")] public static void WriteLine(string message) { TraceInternal.WriteLine(message); } /// /// Writes the name of the value /// parameter followed by a line terminator to the /// trace listeners in the collection. The default line /// terminator is a carriage return followed by a line feed (\r\n). /// [System.Diagnostics.Conditional("DEBUG")] public static void WriteLine(object value) { TraceInternal.WriteLine(value); } /// /// Writes a category name and message followed by a line terminator to the trace /// listeners in the collection. The default line /// terminator is a carriage return followed by a line feed (\r\n). /// [System.Diagnostics.Conditional("DEBUG")] public static void WriteLine(string message, string category) { TraceInternal.WriteLine(message, category); } /// /// Writes a category name and the name of the value /// parameter followed by a line /// terminator to the trace listeners in the collection. The /// default line terminator is a carriage return followed by a line feed (\r\n). /// [System.Diagnostics.Conditional("DEBUG")] public static void WriteLine(object value, string category) { TraceInternal.WriteLine(value, category); } /// /// Writes a category name and the name of the value /// parameter followed by a line /// terminator to the trace listeners in the collection. The /// default line terminator is a carriage return followed by a line feed (\r\n). /// [System.Diagnostics.Conditional("DEBUG")] public static void WriteLine(string format, params object[] args) { TraceInternal.WriteLine(String.Format(CultureInfo.InvariantCulture, format, args)); } /// /// Writes a message to the trace listeners in the collection /// if a condition is /// . /// [System.Diagnostics.Conditional("DEBUG")] public static void WriteIf(bool condition, string message) { TraceInternal.WriteIf(condition, message); } /// /// Writes the name of the value /// parameter to the trace listeners in the /// collection if a condition is /// . /// [System.Diagnostics.Conditional("DEBUG")] public static void WriteIf(bool condition, object value) { TraceInternal.WriteIf(condition, value); } /// /// Writes a category name and message /// to the trace listeners in the /// collection if a condition is /// . /// [System.Diagnostics.Conditional("DEBUG")] public static void WriteIf(bool condition, string message, string category) { TraceInternal.WriteIf(condition, message, category); } /// /// Writes a category name and the name of the value /// parameter to the trace /// listeners in the collection if a condition is /// . /// [System.Diagnostics.Conditional("DEBUG")] public static void WriteIf(bool condition, object value, string category) { TraceInternal.WriteIf(condition, value, category); } /// /// Writes a message followed by a line terminator to the trace listeners in the /// collection if a condition is /// . The default line terminator is a carriage return followed /// by a line feed (\r\n). /// [System.Diagnostics.Conditional("DEBUG")] public static void WriteLineIf(bool condition, string message) { TraceInternal.WriteLineIf(condition, message); } /// /// Writes the name of the value /// parameter followed by a line terminator to the /// trace listeners in the collection if a condition is /// . The default line terminator is a carriage return followed /// by a line feed (\r\n). /// [System.Diagnostics.Conditional("DEBUG")] public static void WriteLineIf(bool condition, object value) { TraceInternal.WriteLineIf(condition, value); } /// /// Writes a category name and message /// followed by a line terminator to the trace /// listeners in the collection if a condition is /// . The default line terminator is a carriage return followed /// by a line feed (\r\n). /// [System.Diagnostics.Conditional("DEBUG")] public static void WriteLineIf(bool condition, string message, string category) { TraceInternal.WriteLineIf(condition, message, category); } /// /// Writes a category name and the name of the value parameter followed by a line /// terminator to the trace listeners in the collection /// if a condition is . The default line terminator is a carriage /// return followed by a line feed (\r\n). /// [System.Diagnostics.Conditional("DEBUG")] public static void WriteLineIf(bool condition, object value, string category) { TraceInternal.WriteLineIf(condition, value, category); } /// /// [To be supplied.] /// [System.Diagnostics.Conditional("DEBUG")] public static void Indent() { TraceInternal.Indent(); } /// /// [To be supplied.] /// [System.Diagnostics.Conditional("DEBUG")] public static void Unindent() { TraceInternal.Unindent(); } #else static readonly object s_ForLock = new Object(); // This is the number of characters that OutputDebugString chunks at. const int internalWriteSize = 4091; [System.Diagnostics.Conditional("DEBUG")] public static void Assert(bool condition) { Assert(condition, String.Empty, String.Empty); } [System.Diagnostics.Conditional("DEBUG")] public static void Assert(bool condition, string message) { Assert(condition, message, String.Empty); } [System.Diagnostics.Conditional("DEBUG")] [System.Security.SecuritySafeCritical] public static void Assert(bool condition, string message, string detailMessage) { if (!condition) { StackTrace stack = new StackTrace(true); int userStackFrameIndex = 0; string stackTrace; try { stackTrace = StackTraceToString(stack, userStackFrameIndex, stack.FrameCount - 1); } catch { stackTrace = ""; } WriteAssert(stackTrace, message, detailMessage); AssertWrapper.ShowAssert(stackTrace, stack.GetFrame(userStackFrameIndex), message, detailMessage); } } [System.Diagnostics.Conditional("DEBUG")] public static void Fail(string message) { Assert(false, message, String.Empty); } [System.Diagnostics.Conditional("DEBUG")] public static void Fail(string message, string detailMessage) { Assert(false, message, detailMessage); } // Given a stack trace and start and end frame indexes, construct a // callstack that contains method, file and line number information. [System.Security.SecuritySafeCritical] private static string StackTraceToString(StackTrace trace, int startFrameIndex, int endFrameIndex) { StringBuilder sb = new StringBuilder(512); for (int i = startFrameIndex; i <= endFrameIndex; i++) { StackFrame frame = trace.GetFrame(i); MethodBase method = frame.GetMethod(); sb.Append(Environment.NewLine); sb.Append(" at "); if (method.ReflectedType != null) { sb.Append(method.ReflectedType.Name); } else { // This is for global methods and this is what shows up in windbg. sb.Append(""); } sb.Append("."); sb.Append(method.Name); sb.Append("("); ParameterInfo[] parameters = method.GetParameters(); for (int j = 0; j < parameters.Length; j++) { ParameterInfo parameter = parameters[j]; if (j > 0) sb.Append(", "); sb.Append(parameter.ParameterType.Name); sb.Append(" "); sb.Append(parameter.Name); } sb.Append(") "); sb.Append(frame.GetFileName()); int line = frame.GetFileLineNumber(); if (line > 0) { sb.Append("("); sb.Append(line.ToString(CultureInfo.InvariantCulture)); sb.Append(")"); } } sb.Append(Environment.NewLine); return sb.ToString(); } private static void WriteAssert(string stackTrace, string message, string detailMessage) { string assertMessage = SR.GetString(SR.DebugAssertBanner) + Environment.NewLine + SR.GetString(SR.DebugAssertShortMessage) + Environment.NewLine + message + Environment.NewLine + SR.GetString(SR.DebugAssertLongMessage) + Environment.NewLine + detailMessage + Environment.NewLine + stackTrace; WriteLine(assertMessage); } [System.Diagnostics.Conditional("DEBUG")] public static void Assert(bool condition, string message, string detailMessageFormat, params object[] args) { Assert(condition, message, String.Format(detailMessageFormat, args)); } [System.Diagnostics.Conditional("DEBUG")] public static void WriteLine(string message) { message = message + "\r\n"; // Use Windows end line on *all* Platforms Write(message); } [System.Diagnostics.Conditional("DEBUG")] public static void Write(string message) { // We don't want output from multiple threads to be interleaved. lock (s_ForLock) { // really huge messages mess up both VS and dbmon, so we chop it up into // reasonable chunks if it's too big if (message == null || message.Length <= internalWriteSize) { internalWrite(message); } else { int offset; for (offset = 0; offset < message.Length - internalWriteSize; offset += internalWriteSize) { internalWrite(message.Substring(offset, internalWriteSize)); } internalWrite(message.Substring(offset)); } } } [System.Security.SecuritySafeCritical] private static void internalWrite(string message) { if (Debugger.IsLogging()) { Debugger.Log(0, null, message); #if !FEATURE_PAL } else { if (message == null) Microsoft.Win32.SafeNativeMethods.OutputDebugString(String.Empty); else Microsoft.Win32.SafeNativeMethods.OutputDebugString(message); #endif //!FEATURE_PAL } } [System.Diagnostics.Conditional("DEBUG")] public static void WriteLine(object value) { WriteLine((value == null) ? String.Empty : value.ToString()); } [System.Diagnostics.Conditional("DEBUG")] public static void WriteLine(object value, string category) { WriteLine((value == null) ? String.Empty : value.ToString(), category); } [System.Diagnostics.Conditional("DEBUG")] public static void WriteLine(string format, params object[] args) { WriteLine(String.Format(null, format, args)); } [System.Diagnostics.Conditional("DEBUG")] public static void WriteLine(string message, string category) { if(category == null) { WriteLine(message); } else { WriteLine(category + ":" + ((message == null) ? String.Empty: message)); } } [System.Diagnostics.Conditional("DEBUG")] public static void Write(object value) { Write((value == null) ? String.Empty : value.ToString()); } [System.Diagnostics.Conditional("DEBUG")] public static void Write(string message, string category) { if(category == null) { Write(message); } else { Write(category + ":" + ((message == null) ? String.Empty: message)); } } [System.Diagnostics.Conditional("DEBUG")] public static void Write(object value, string category) { Write((value == null) ? String.Empty : value.ToString(), category); } [System.Diagnostics.Conditional("DEBUG")] public static void WriteIf(bool condition, string message) { if(condition) { Write(message); } } [System.Diagnostics.Conditional("DEBUG")] public static void WriteIf(bool condition, object value) { if(condition) { Write(value); } } [System.Diagnostics.Conditional("DEBUG")] public static void WriteIf(bool condition, string message, string category) { if(condition) { Write(message, category); } } [System.Diagnostics.Conditional("DEBUG")] public static void WriteIf(bool condition, object value, string category) { if(condition) { Write(value, category); } } [System.Diagnostics.Conditional("DEBUG")] public static void WriteLineIf(bool condition, object value) { if(condition) { WriteLine(value); } } [System.Diagnostics.Conditional("DEBUG")] public static void WriteLineIf(bool condition, object value, string category) { if(condition) { WriteLine(value, category); } } #if FEATURE_NETCORE [System.Diagnostics.Conditional("DEBUG")] public static void WriteLineIf(bool condition, string message) { if(condition) { WriteLine(message); } } [System.Diagnostics.Conditional("DEBUG")] // This is used by our compression code. public static void WriteLineIf(bool condition, string message, string category) { if (condition) { WriteLine(message, category); } } #endif // FEATURE_NETCORE #endif // SILVERLIGHT } }