AvTrace.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Base / MS / Internal / AvTrace.cs / 1 / AvTrace.cs

                            /****************************************************************************\
*
* File: AvTrace.cs
* 
* This class wraps a System.Diagnostics.TraceSource.  The purpose of
* wrapping is so that we can have a common point of enabling/disabling 
* without perf effect.  This is also where we standardize the output 
* we produce, to enable more effective trace filters, trace listeners,
* and post-processing tools. 
*
* Copyright (C) by Microsoft Corporation.  All rights reserved.
*
\***************************************************************************/ 

#define TRACE 
 
using System;
using System.Diagnostics; 
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Reflection; 
using System.Collections;
using System.Windows; 
 
using Microsoft.Win32;
using MS.Win32; 
using MS.Internal.WindowsBase;

namespace MS.Internal
{ 

    internal class AvTrace 
    { 
        //
        //  AvTrace constructor 
        //
        //  Parameters:
        //      getTraceSourceDelegate and clearTraceSourceDelegate are for accessing the
        //      TraceSource (that corresponds to this AvTrace) from PresentationTraceSources. 
        //
 
        public AvTrace( GetTraceSourceDelegate getTraceSourceDelegate, ClearTraceSourceDelegate clearTraceSourceDelegate ) 
        {
            _getTraceSourceDelegate = getTraceSourceDelegate; 
            _clearTraceSourceDelegate = clearTraceSourceDelegate;

            // Get notified when we need to check the registry and debugger attached-ness.
            PresentationTraceSources.TraceRefresh += new TraceRefreshEventHandler(Refresh); 

            // Fetch and cache the TraceSource from PresentationTraceSources 
            Initialize(); 
        }
 

        //
        //  Refresh this trace source -- see if it needs to be enabled
        //  because registry setting has changed or debugger is attached. 
        //
        //  To re-read the config file, call System.Diagnostics.Trace.Refresh() . 
        // 

        public void Refresh() 
        {
            // Cause the registry to be re-read in case it's changed.
            _enabledInRegistry = null;
 
            // Re-initialize everything
            Initialize(); 
        } 

        // 
        //  Don't call Trace unless this property is true.
        //  Note that this can be false, even though IsEnabledOverride is true (this happens when
        //  running under a debugger).  See IsEnabledOverride for a description.
        // 

        public bool IsEnabled 
        { 
            get { return _isEnabled; }
        } 

        //
        // If this flag is set, Trace doesn't automatically add the .GetHashCode and .GetType
        // to the format string. 
        //
 
        public bool SuppressGeneratedParameters 
        {
            get { return _suppressGeneratedParameters; } 
            set { _suppressGeneratedParameters = value; }
        }

        // 
        //  IsEnabledOverride is used as a special override.  This can be true even if IsEnabled is false.
        //  The scenario is for >=Warning traces; in this case, despite the fact that tracing wasn't enabled 
        //  in the registry, we want to send traces anyway if a debugger is attached.  Clients of the trace classes 
        //  have to decide to call IsEnabledOverride in these cases rather than IsEnabled.
        //  Note that this could be cleaner, but was done to minimize risk as a late checkin; the key goal being 
        //  that tracing only run when enabled.
        //

        public bool IsEnabledOverride 
        {
            get { return _traceSource != null; } 
        } 

        // 
        // EnabledByDebugger is a special override that causes AvTrace to be IsEnabled, when we're running
        // under a debugger, despite the fact that the registry hasn't enabled tracing.  This was added
        // so that TraceData could cause tracing to be enabled when running under the debugger.  Other classes
        // only enable tracing based on the registry key.  See also the common on IsEnabledOverride.  And like the note there, 
        // this couuld be more straightforward, but is designed this way to mitigate risk.
        // 
 
        public bool EnabledByDebugger
        { 
            get { return _enabledByDebugger; }

            set
            { 
                _enabledByDebugger = value;
                if( _enabledByDebugger ) 
                { 
                    if( !IsEnabled && IsDebuggerAttached() )
                    { 
                        _isEnabled = true;
                    }
                }
                else 
                {
                    if( IsEnabled && !IsWpfTracingEnabledInRegistry() && !_hasBeenRefreshed ) 
                    { 
                        _isEnabled = false;
                    } 
                }
            }
        }
 
        //
        // This method is called to indicate that PresentationTraceSources.Refresh 
        // has been called.  When that method has been called, we'll allow 
        // tracing to be enabled.
        // 

        static public void OnRefresh()
        {
            _hasBeenRefreshed = true; 
        }
 
 
        //
        // Extra args passed to Trace call will be forwarded to listeners of TraceExtraMessages 
        //

        public event AvTraceEventHandler TraceExtraMessages;
 

        // 
        // Internal initialization 
        //
        void Initialize( ) 
        {
            // Decide if we should actually create a TraceSource instance (doing so isn't free,
            // so we don't want to do it if we can avoid it).
 
            if( ShouldCreateTraceSources() )
            { 
                // Get TraceSource from the PresentationTraceSources 
                // (this call will indirectly create the TraceSource if one doesn't already exist)
                _traceSource = _getTraceSourceDelegate(); 

                // We go enabled if tracing is enabled in the registry, if
                // PresentationTraceSources.Refresh has been called, or if we're in the debugger
                // and the debugger is supposed to enable tracing. 
                _isEnabled = IsWpfTracingEnabledInRegistry() || _hasBeenRefreshed || _enabledByDebugger ;
            } 
            else 
            {
                _clearTraceSourceDelegate(); 
                _traceSource = null;
                _isEnabled = false;
            }
        } 

 
        // 
        //  See if tracing should be enabled.  It should if we're in
        //  a debugger, or if the registry key is set, or if 
        //  PresentationTraceSources.Refresh has been called.
        //  (We do this so that in the default case, we don't even create
        //  the TraceSource.)
        // 

        static private bool ShouldCreateTraceSources() 
        { 
            if( IsWpfTracingEnabledInRegistry()
                || IsDebuggerAttached() 
                || _hasBeenRefreshed
              )
            {
                return true; 
            }
 
            return false; 

        } 



       /// 
       ///  Read the registry to see if WPF tracing is allowed
       /// 
       /// 
       /// Critical - Calls critical code (ReadRegistryValue)
       /// TreatAsSafe - We consider this safe to expose from the internet, because 
       ///     the value being read is just a flag which enables/disables tracing,
       ///     and it is only read.  The flag is "ManagedTracing", unber HKCU.  If it is set to
       ///     1, tracing (from System.Diagnostics) can be enabled/configured using a .config file.
       /// 

       [SecurityCritical, SecurityTreatAsSafe] 
       [FriendAccessAllowed] 
       static internal bool IsWpfTracingEnabledInRegistry()
       { 
            // First time this is called, initialize from the registry

            if( _enabledInRegistry == null )
            { 
                bool enabled = false;
 
                object keyValue = SecurityHelper.ReadRegistryValue( 
                                                            Registry.CurrentUser,
                                                            @"Software\Microsoft\Tracing\WPF", 
                                                            "ManagedTracing");

                if( keyValue is int && ((int) keyValue) == 1 )
                { 
                    enabled = true;
                } 
 
                // Update the static.  Doing this last protects us from threading problems; worse case, multiple
                // threads will set the same value into it. 
                _enabledInRegistry = enabled;

            }
 
            return (bool) _enabledInRegistry;
 
        } 

 

        //
        // Check for an attached debugger.
        // 

        internal static bool IsDebuggerAttached() 
        { 
            return Debugger.IsAttached || SafeNativeMethods.IsDebuggerPresent();
        } 


        //
        //  Trace an event 
        //
        //  note: labels start at index 1, parameters start at index 0 
        // 

        public void Trace( TraceEventType type, int eventId, string message, string[] labels, object[] parameters ) 
        {
            // Don't bother building the string if this trace is going to be ignored.

            if( _traceSource == null 
                || !_traceSource.Switch.ShouldTrace( type ))
            { 
                return; 
            }
 

            // Compose the trace string.

            AvTraceBuilder traceBuilder = new AvTraceBuilder(message); // Holds the format string 
            ArrayList arrayList = new ArrayList(); // Holds the combined labels & parameters arrays.
 
            int formatIndex = 0; 

            if (parameters != null && labels != null && labels.Length > 0) 
            {
                int i = 1, j = 0;
                for( ; i < labels.Length && j < parameters.Length; i++, j++ )
                { 
                    // Append to the format string a "; {0} = '{1}'", where the index increments (e.g. the second iteration will
                    // produce {2} & {3}). 
 
                    traceBuilder.Append("; {" + (formatIndex++).ToString() + "}='{" + (formatIndex++).ToString() + "}'" );
 
                    // If this parameter is null, convert to ""; otherwise, when a string.format is ultimately called
                    // it produces bad results.

                    if( parameters[j] == null ) 
                    {
                        parameters[j] = ""; 
                    } 

                    // Otherwise, if this is an interesting object, add the hash code and type to 
                    // the format string explicitely.

                    else if( !SuppressGeneratedParameters
                             && parameters[j].GetType() != typeof(string) 
                             && !(parameters[j] is ValueType)
                             && !(parameters[j] is Type) 
                             && !(parameters[j] is DependencyProperty) ) 
                    {
                        traceBuilder.Append("; " + labels[i].ToString() + ".HashCode='" 
                                                    + GetHashCodeHelper(parameters[j]).ToString() + "'" );

                        traceBuilder.Append("; " + labels[i].ToString() + ".Type='"
                                                    + GetTypeHelper(parameters[j]).ToString() + "'" ); 
                    }
 
 
                    // Add the label & parameter to the combined list.
                    // (As an optimization, the generated classes could pre-allocate a thread-safe static array, to avoid 
                    // this allocation and the ToArray allocation below.)

                    arrayList.Add( labels[i] );
                    arrayList.Add( parameters[j] ); 

 
                } 

                // It's OK if we terminate because we have more lables than parameters; 
                // this is used by traces to have out-values in the Stop message.

                if( TraceExtraMessages != null && j < parameters.Length)
                { 
                    TraceExtraMessages( traceBuilder, parameters, j );
                } 
 
            }
 
            // Send the trace

            _traceSource.TraceEvent(
                type, 
                eventId,
                traceBuilder.ToString(), 
                arrayList.ToArray() ); 

            // When in the debugger, always flush the output, to guarantee that the 
            // traces and other info (e.g. exceptions) get interleaved correctly.

            if( IsDebuggerAttached() )
            { 
                _traceSource.Flush();
            } 
 
        }
 

        //
        //  Trace an event, as both a TraceEventType.Start and TraceEventType.Stop.
        //  (information is contained in the Start event) 
        //
 
        public void TraceStartStop( int eventID, string message, string[] labels, Object[] parameters ) 
        {
            Trace( TraceEventType.Start, eventID, message, labels, parameters ); 
            _traceSource.TraceEvent( TraceEventType.Stop, eventID);
        }

 
        //
        //  Convert the value to a string, even if the system conversion throws 
        //  an exception. 
        //
 
        static public string ToStringHelper(object value)
        {
            if (value == null)
                return ""; 

            // PreSharp uses message numbers that the C# compiler doesn't know about. 
            // Disable the C# complaints, per the PreSharp documentation. 
            #pragma warning disable 1634, 1691
 
            // PreSharp complains about catching NullReference (and other) exceptions.
            // In this case, these are precisely the ones we want to catch the most,
            // so that we can still print some kind of diagnostic information even
            // about objects that implement ToString poorly. 
            #pragma warning disable 56500
 
            string result; 
            try
            { 
                result = value.ToString();
            }
            catch
            { 
                result = "";
            } 
 
            #pragma warning restore 56500
            #pragma warning restore 1634, 1691 

            return result;
        }
 

        // 
        //  Return the type name for the given value 
        //
 
        static public string TypeName(object value)
        {
            if (value == null)
                return ""; 

            return value.GetType().Name; 
        } 

        // 
        // This is a wrapper around Object.GetHashCode.  We use this because
        // individual GetHashCode implementations can be unreliable.
        //
 
        static public int GetHashCodeHelper(object value )
        { 
            try 
            {
                return (value != null) ? value.GetHashCode() : 0; 
            }
            catch( Exception e )
            {
                if( CriticalExceptions.IsCriticalException(e) 
                    &&
                    !(e is System.NullReferenceException) ) 
                { 
                    throw;
                } 

                return 0;
            }
 
        }
 
 
        //
        // Get an object's type, returning typeof(ValueType) for 
        // the null case.
        //

        static public Type GetTypeHelper(object value) 
        {
            if (value == null) 
            { 
                return typeof(ValueType);
            } 

            return value.GetType();
        }
 

        // 
        // Private state 
        //
 
        // Flag showing if tracing is enabled.  See also the IsEnabledOverride property
        bool _isEnabled = false;

        // If this is set, then having the debugger attached is an excuse to be enabled, 
        // even if the registry flag isn't set.
        bool _enabledByDebugger = false; 
 
        // If this flag is set, Trace doesn't automatically add the .GetHashCode and .GetType
        // to the format string. 
        bool _suppressGeneratedParameters = false;

        // If this flag is set, tracing will be enabled, as if it was set in the registry.
        static bool _hasBeenRefreshed = false; 

        // Delegates to create and remove the TraceSource instance 
        GetTraceSourceDelegate _getTraceSourceDelegate; 
        ClearTraceSourceDelegate _clearTraceSourceDelegate;
 
        // Cache of TraceSource instance; real value resides in PresentationTraceSources.
        TraceSource _traceSource;

        // Cache used by IsWpfTracingEnabledInRegistry 
        static Nullable _enabledInRegistry = null;
 
 
    }
 
    internal delegate void AvTraceEventHandler( AvTraceBuilder traceBuilder, object[] parameters, int start );

    internal class AvTraceBuilder
    { 
        StringBuilder  _sb;
 
        public AvTraceBuilder() 
        {
            _sb = new StringBuilder(); 
        }

        public AvTraceBuilder( string message )
        { 
            _sb = new StringBuilder( message );
        } 
 
        public void Append( string message )
        { 
            _sb.Append( message );
        }

        public void AppendFormat( string message, params object[] args ) 
        {
            object[] argstrs = new object[args.Length]; 
            for (int i = 0; i < args.Length; ++i) 
            {
                string s = args[i] as string; 
                argstrs[i] = (s != null) ? s : AvTrace.ToStringHelper(args[i]);
            }
            _sb.AppendFormat( message, argstrs );
        } 

        public void AppendFormat( string message, object arg1 ) 
        { 
            _sb.AppendFormat( message, new object[] { AvTrace.ToStringHelper(arg1) } );
        } 

        public void AppendFormat( string message, object arg1, object arg2 )
        {
            _sb.AppendFormat( message, new object[] { AvTrace.ToStringHelper(arg1), AvTrace.ToStringHelper(arg2) } ); 
        }
 
        public void AppendFormat( string message, string arg1 ) 
        {
            _sb.AppendFormat( message, new object[] { arg1 } ); 
        }

        public void AppendFormat( string message, string arg1, string arg2 )
        { 
            _sb.AppendFormat( message, new object[] { arg1, arg2 } );
        } 
 
        public override string ToString( )
        { 
            return _sb.ToString();
        }

    } 

    internal delegate TraceSource GetTraceSourceDelegate(); 
    internal delegate void ClearTraceSourceDelegate(); 

 

}

 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
 
/****************************************************************************\
*
* File: AvTrace.cs
* 
* This class wraps a System.Diagnostics.TraceSource.  The purpose of
* wrapping is so that we can have a common point of enabling/disabling 
* without perf effect.  This is also where we standardize the output 
* we produce, to enable more effective trace filters, trace listeners,
* and post-processing tools. 
*
* Copyright (C) by Microsoft Corporation.  All rights reserved.
*
\***************************************************************************/ 

#define TRACE 
 
using System;
using System.Diagnostics; 
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Reflection; 
using System.Collections;
using System.Windows; 
 
using Microsoft.Win32;
using MS.Win32; 
using MS.Internal.WindowsBase;

namespace MS.Internal
{ 

    internal class AvTrace 
    { 
        //
        //  AvTrace constructor 
        //
        //  Parameters:
        //      getTraceSourceDelegate and clearTraceSourceDelegate are for accessing the
        //      TraceSource (that corresponds to this AvTrace) from PresentationTraceSources. 
        //
 
        public AvTrace( GetTraceSourceDelegate getTraceSourceDelegate, ClearTraceSourceDelegate clearTraceSourceDelegate ) 
        {
            _getTraceSourceDelegate = getTraceSourceDelegate; 
            _clearTraceSourceDelegate = clearTraceSourceDelegate;

            // Get notified when we need to check the registry and debugger attached-ness.
            PresentationTraceSources.TraceRefresh += new TraceRefreshEventHandler(Refresh); 

            // Fetch and cache the TraceSource from PresentationTraceSources 
            Initialize(); 
        }
 

        //
        //  Refresh this trace source -- see if it needs to be enabled
        //  because registry setting has changed or debugger is attached. 
        //
        //  To re-read the config file, call System.Diagnostics.Trace.Refresh() . 
        // 

        public void Refresh() 
        {
            // Cause the registry to be re-read in case it's changed.
            _enabledInRegistry = null;
 
            // Re-initialize everything
            Initialize(); 
        } 

        // 
        //  Don't call Trace unless this property is true.
        //  Note that this can be false, even though IsEnabledOverride is true (this happens when
        //  running under a debugger).  See IsEnabledOverride for a description.
        // 

        public bool IsEnabled 
        { 
            get { return _isEnabled; }
        } 

        //
        // If this flag is set, Trace doesn't automatically add the .GetHashCode and .GetType
        // to the format string. 
        //
 
        public bool SuppressGeneratedParameters 
        {
            get { return _suppressGeneratedParameters; } 
            set { _suppressGeneratedParameters = value; }
        }

        // 
        //  IsEnabledOverride is used as a special override.  This can be true even if IsEnabled is false.
        //  The scenario is for >=Warning traces; in this case, despite the fact that tracing wasn't enabled 
        //  in the registry, we want to send traces anyway if a debugger is attached.  Clients of the trace classes 
        //  have to decide to call IsEnabledOverride in these cases rather than IsEnabled.
        //  Note that this could be cleaner, but was done to minimize risk as a late checkin; the key goal being 
        //  that tracing only run when enabled.
        //

        public bool IsEnabledOverride 
        {
            get { return _traceSource != null; } 
        } 

        // 
        // EnabledByDebugger is a special override that causes AvTrace to be IsEnabled, when we're running
        // under a debugger, despite the fact that the registry hasn't enabled tracing.  This was added
        // so that TraceData could cause tracing to be enabled when running under the debugger.  Other classes
        // only enable tracing based on the registry key.  See also the common on IsEnabledOverride.  And like the note there, 
        // this couuld be more straightforward, but is designed this way to mitigate risk.
        // 
 
        public bool EnabledByDebugger
        { 
            get { return _enabledByDebugger; }

            set
            { 
                _enabledByDebugger = value;
                if( _enabledByDebugger ) 
                { 
                    if( !IsEnabled && IsDebuggerAttached() )
                    { 
                        _isEnabled = true;
                    }
                }
                else 
                {
                    if( IsEnabled && !IsWpfTracingEnabledInRegistry() && !_hasBeenRefreshed ) 
                    { 
                        _isEnabled = false;
                    } 
                }
            }
        }
 
        //
        // This method is called to indicate that PresentationTraceSources.Refresh 
        // has been called.  When that method has been called, we'll allow 
        // tracing to be enabled.
        // 

        static public void OnRefresh()
        {
            _hasBeenRefreshed = true; 
        }
 
 
        //
        // Extra args passed to Trace call will be forwarded to listeners of TraceExtraMessages 
        //

        public event AvTraceEventHandler TraceExtraMessages;
 

        // 
        // Internal initialization 
        //
        void Initialize( ) 
        {
            // Decide if we should actually create a TraceSource instance (doing so isn't free,
            // so we don't want to do it if we can avoid it).
 
            if( ShouldCreateTraceSources() )
            { 
                // Get TraceSource from the PresentationTraceSources 
                // (this call will indirectly create the TraceSource if one doesn't already exist)
                _traceSource = _getTraceSourceDelegate(); 

                // We go enabled if tracing is enabled in the registry, if
                // PresentationTraceSources.Refresh has been called, or if we're in the debugger
                // and the debugger is supposed to enable tracing. 
                _isEnabled = IsWpfTracingEnabledInRegistry() || _hasBeenRefreshed || _enabledByDebugger ;
            } 
            else 
            {
                _clearTraceSourceDelegate(); 
                _traceSource = null;
                _isEnabled = false;
            }
        } 

 
        // 
        //  See if tracing should be enabled.  It should if we're in
        //  a debugger, or if the registry key is set, or if 
        //  PresentationTraceSources.Refresh has been called.
        //  (We do this so that in the default case, we don't even create
        //  the TraceSource.)
        // 

        static private bool ShouldCreateTraceSources() 
        { 
            if( IsWpfTracingEnabledInRegistry()
                || IsDebuggerAttached() 
                || _hasBeenRefreshed
              )
            {
                return true; 
            }
 
            return false; 

        } 



       /// 
       ///  Read the registry to see if WPF tracing is allowed
       /// 
       /// 
       /// Critical - Calls critical code (ReadRegistryValue)
       /// TreatAsSafe - We consider this safe to expose from the internet, because 
       ///     the value being read is just a flag which enables/disables tracing,
       ///     and it is only read.  The flag is "ManagedTracing", unber HKCU.  If it is set to
       ///     1, tracing (from System.Diagnostics) can be enabled/configured using a .config file.
       /// 

       [SecurityCritical, SecurityTreatAsSafe] 
       [FriendAccessAllowed] 
       static internal bool IsWpfTracingEnabledInRegistry()
       { 
            // First time this is called, initialize from the registry

            if( _enabledInRegistry == null )
            { 
                bool enabled = false;
 
                object keyValue = SecurityHelper.ReadRegistryValue( 
                                                            Registry.CurrentUser,
                                                            @"Software\Microsoft\Tracing\WPF", 
                                                            "ManagedTracing");

                if( keyValue is int && ((int) keyValue) == 1 )
                { 
                    enabled = true;
                } 
 
                // Update the static.  Doing this last protects us from threading problems; worse case, multiple
                // threads will set the same value into it. 
                _enabledInRegistry = enabled;

            }
 
            return (bool) _enabledInRegistry;
 
        } 

 

        //
        // Check for an attached debugger.
        // 

        internal static bool IsDebuggerAttached() 
        { 
            return Debugger.IsAttached || SafeNativeMethods.IsDebuggerPresent();
        } 


        //
        //  Trace an event 
        //
        //  note: labels start at index 1, parameters start at index 0 
        // 

        public void Trace( TraceEventType type, int eventId, string message, string[] labels, object[] parameters ) 
        {
            // Don't bother building the string if this trace is going to be ignored.

            if( _traceSource == null 
                || !_traceSource.Switch.ShouldTrace( type ))
            { 
                return; 
            }
 

            // Compose the trace string.

            AvTraceBuilder traceBuilder = new AvTraceBuilder(message); // Holds the format string 
            ArrayList arrayList = new ArrayList(); // Holds the combined labels & parameters arrays.
 
            int formatIndex = 0; 

            if (parameters != null && labels != null && labels.Length > 0) 
            {
                int i = 1, j = 0;
                for( ; i < labels.Length && j < parameters.Length; i++, j++ )
                { 
                    // Append to the format string a "; {0} = '{1}'", where the index increments (e.g. the second iteration will
                    // produce {2} & {3}). 
 
                    traceBuilder.Append("; {" + (formatIndex++).ToString() + "}='{" + (formatIndex++).ToString() + "}'" );
 
                    // If this parameter is null, convert to ""; otherwise, when a string.format is ultimately called
                    // it produces bad results.

                    if( parameters[j] == null ) 
                    {
                        parameters[j] = ""; 
                    } 

                    // Otherwise, if this is an interesting object, add the hash code and type to 
                    // the format string explicitely.

                    else if( !SuppressGeneratedParameters
                             && parameters[j].GetType() != typeof(string) 
                             && !(parameters[j] is ValueType)
                             && !(parameters[j] is Type) 
                             && !(parameters[j] is DependencyProperty) ) 
                    {
                        traceBuilder.Append("; " + labels[i].ToString() + ".HashCode='" 
                                                    + GetHashCodeHelper(parameters[j]).ToString() + "'" );

                        traceBuilder.Append("; " + labels[i].ToString() + ".Type='"
                                                    + GetTypeHelper(parameters[j]).ToString() + "'" ); 
                    }
 
 
                    // Add the label & parameter to the combined list.
                    // (As an optimization, the generated classes could pre-allocate a thread-safe static array, to avoid 
                    // this allocation and the ToArray allocation below.)

                    arrayList.Add( labels[i] );
                    arrayList.Add( parameters[j] ); 

 
                } 

                // It's OK if we terminate because we have more lables than parameters; 
                // this is used by traces to have out-values in the Stop message.

                if( TraceExtraMessages != null && j < parameters.Length)
                { 
                    TraceExtraMessages( traceBuilder, parameters, j );
                } 
 
            }
 
            // Send the trace

            _traceSource.TraceEvent(
                type, 
                eventId,
                traceBuilder.ToString(), 
                arrayList.ToArray() ); 

            // When in the debugger, always flush the output, to guarantee that the 
            // traces and other info (e.g. exceptions) get interleaved correctly.

            if( IsDebuggerAttached() )
            { 
                _traceSource.Flush();
            } 
 
        }
 

        //
        //  Trace an event, as both a TraceEventType.Start and TraceEventType.Stop.
        //  (information is contained in the Start event) 
        //
 
        public void TraceStartStop( int eventID, string message, string[] labels, Object[] parameters ) 
        {
            Trace( TraceEventType.Start, eventID, message, labels, parameters ); 
            _traceSource.TraceEvent( TraceEventType.Stop, eventID);
        }

 
        //
        //  Convert the value to a string, even if the system conversion throws 
        //  an exception. 
        //
 
        static public string ToStringHelper(object value)
        {
            if (value == null)
                return ""; 

            // PreSharp uses message numbers that the C# compiler doesn't know about. 
            // Disable the C# complaints, per the PreSharp documentation. 
            #pragma warning disable 1634, 1691
 
            // PreSharp complains about catching NullReference (and other) exceptions.
            // In this case, these are precisely the ones we want to catch the most,
            // so that we can still print some kind of diagnostic information even
            // about objects that implement ToString poorly. 
            #pragma warning disable 56500
 
            string result; 
            try
            { 
                result = value.ToString();
            }
            catch
            { 
                result = "";
            } 
 
            #pragma warning restore 56500
            #pragma warning restore 1634, 1691 

            return result;
        }
 

        // 
        //  Return the type name for the given value 
        //
 
        static public string TypeName(object value)
        {
            if (value == null)
                return ""; 

            return value.GetType().Name; 
        } 

        // 
        // This is a wrapper around Object.GetHashCode.  We use this because
        // individual GetHashCode implementations can be unreliable.
        //
 
        static public int GetHashCodeHelper(object value )
        { 
            try 
            {
                return (value != null) ? value.GetHashCode() : 0; 
            }
            catch( Exception e )
            {
                if( CriticalExceptions.IsCriticalException(e) 
                    &&
                    !(e is System.NullReferenceException) ) 
                { 
                    throw;
                } 

                return 0;
            }
 
        }
 
 
        //
        // Get an object's type, returning typeof(ValueType) for 
        // the null case.
        //

        static public Type GetTypeHelper(object value) 
        {
            if (value == null) 
            { 
                return typeof(ValueType);
            } 

            return value.GetType();
        }
 

        // 
        // Private state 
        //
 
        // Flag showing if tracing is enabled.  See also the IsEnabledOverride property
        bool _isEnabled = false;

        // If this is set, then having the debugger attached is an excuse to be enabled, 
        // even if the registry flag isn't set.
        bool _enabledByDebugger = false; 
 
        // If this flag is set, Trace doesn't automatically add the .GetHashCode and .GetType
        // to the format string. 
        bool _suppressGeneratedParameters = false;

        // If this flag is set, tracing will be enabled, as if it was set in the registry.
        static bool _hasBeenRefreshed = false; 

        // Delegates to create and remove the TraceSource instance 
        GetTraceSourceDelegate _getTraceSourceDelegate; 
        ClearTraceSourceDelegate _clearTraceSourceDelegate;
 
        // Cache of TraceSource instance; real value resides in PresentationTraceSources.
        TraceSource _traceSource;

        // Cache used by IsWpfTracingEnabledInRegistry 
        static Nullable _enabledInRegistry = null;
 
 
    }
 
    internal delegate void AvTraceEventHandler( AvTraceBuilder traceBuilder, object[] parameters, int start );

    internal class AvTraceBuilder
    { 
        StringBuilder  _sb;
 
        public AvTraceBuilder() 
        {
            _sb = new StringBuilder(); 
        }

        public AvTraceBuilder( string message )
        { 
            _sb = new StringBuilder( message );
        } 
 
        public void Append( string message )
        { 
            _sb.Append( message );
        }

        public void AppendFormat( string message, params object[] args ) 
        {
            object[] argstrs = new object[args.Length]; 
            for (int i = 0; i < args.Length; ++i) 
            {
                string s = args[i] as string; 
                argstrs[i] = (s != null) ? s : AvTrace.ToStringHelper(args[i]);
            }
            _sb.AppendFormat( message, argstrs );
        } 

        public void AppendFormat( string message, object arg1 ) 
        { 
            _sb.AppendFormat( message, new object[] { AvTrace.ToStringHelper(arg1) } );
        } 

        public void AppendFormat( string message, object arg1, object arg2 )
        {
            _sb.AppendFormat( message, new object[] { AvTrace.ToStringHelper(arg1), AvTrace.ToStringHelper(arg2) } ); 
        }
 
        public void AppendFormat( string message, string arg1 ) 
        {
            _sb.AppendFormat( message, new object[] { arg1 } ); 
        }

        public void AppendFormat( string message, string arg1, string arg2 )
        { 
            _sb.AppendFormat( message, new object[] { arg1, arg2 } );
        } 
 
        public override string ToString( )
        { 
            return _sb.ToString();
        }

    } 

    internal delegate TraceSource GetTraceSourceDelegate(); 
    internal delegate void ClearTraceSourceDelegate(); 

 

}

 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK