Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / AvTrace.cs / 1305600 / 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.Globalization; 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(AntiFormat(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 AntiFormat(result); } // replace { and } by {{ and }} - call if literal string will be passed to Format static public string AntiFormat(string s) { int formatIndex = s.IndexOfAny(FormatChars); if (formatIndex < 0) return s; StringBuilder sb = new StringBuilder(); int index = 0; int lengthMinus1 = s.Length - 1; while (formatIndex >= 0) { if (formatIndex < lengthMinus1 && s[formatIndex] == s[formatIndex+1]) { // formatting character is already duplicated - leave them alone formatIndex = s.IndexOfAny(FormatChars, formatIndex+2); } else { // duplicate the formatting character sb.Append(s.Substring(index, formatIndex - index + 1)); sb.Append(s[formatIndex]); index = formatIndex + 1; formatIndex = s.IndexOfAny(FormatChars, index); } } if (index <= lengthMinus1) { sb.Append(s.Substring(index)); } return sb.ToString(); } // // 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.IsCriticalApplicationException(e)) { 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; static char[] FormatChars = new char[]{ '{', '}' }; } 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( CultureInfo.InvariantCulture, message, argstrs ); } public void AppendFormat( string message, object arg1 ) { _sb.AppendFormat( CultureInfo.InvariantCulture, message, new object[] { AvTrace.ToStringHelper(arg1) } ); } public void AppendFormat( string message, object arg1, object arg2 ) { _sb.AppendFormat( CultureInfo.InvariantCulture, message, new object[] { AvTrace.ToStringHelper(arg1), AvTrace.ToStringHelper(arg2) } ); } public void AppendFormat( string message, string arg1 ) { _sb.AppendFormat( CultureInfo.InvariantCulture, message, new object[] { AvTrace.AntiFormat(arg1) } ); } public void AppendFormat( string message, string arg1, string arg2 ) { _sb.AppendFormat( CultureInfo.InvariantCulture, message, new object[] { AvTrace.AntiFormat(arg1), AvTrace.AntiFormat(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
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ConnectionManagementSection.cs
- dbenumerator.cs
- XmlStreamStore.cs
- CoreSwitches.cs
- CustomGrammar.cs
- Content.cs
- PlainXmlWriter.cs
- FunctionParameter.cs
- MessageContractAttribute.cs
- ReverseInheritProperty.cs
- UnsafeNativeMethods.cs
- pingexception.cs
- IncrementalReadDecoders.cs
- TransformValueSerializer.cs
- SubclassTypeValidator.cs
- ZipIOLocalFileDataDescriptor.cs
- EntityDataSourceWizardForm.cs
- EngineSite.cs
- WorkerRequest.cs
- ISAPIWorkerRequest.cs
- EventEntry.cs
- SafeCloseHandleCritical.cs
- Overlapped.cs
- Int16Converter.cs
- RSAPKCS1KeyExchangeFormatter.cs
- SqlDeflator.cs
- MetadataItem.cs
- StyleHelper.cs
- UserNameSecurityTokenProvider.cs
- DataFormat.cs
- ParallelQuery.cs
- Int32Rect.cs
- RC2CryptoServiceProvider.cs
- MultipartContentParser.cs
- PlanCompilerUtil.cs
- WebPartConnectionsCloseVerb.cs
- SortDescriptionCollection.cs
- WindowsAltTab.cs
- MdiWindowListStrip.cs
- DataGridRowHeader.cs
- SecurityUtils.cs
- StructureChangedEventArgs.cs
- WindowsStartMenu.cs
- CustomAttributeBuilder.cs
- EntityDataSourceColumn.cs
- XmlChildNodes.cs
- Models.cs
- DynamicExpression.cs
- ReceiveActivity.cs
- FindCriteria11.cs
- ListDictionary.cs
- InstanceCreationEditor.cs
- TextContainerHelper.cs
- XmlQualifiedNameTest.cs
- DataListCommandEventArgs.cs
- TemplateXamlParser.cs
- PeerNameResolver.cs
- UshortList2.cs
- TreeNodeCollection.cs
- BinaryReader.cs
- WindowsIPAddress.cs
- CompilerGlobalScopeAttribute.cs
- DataSourceXmlClassAttribute.cs
- ValidationErrorEventArgs.cs
- GorillaCodec.cs
- ASCIIEncoding.cs
- XmlSchemaAnyAttribute.cs
- FormsAuthentication.cs
- Rijndael.cs
- ChannelTokenTypeConverter.cs
- UnknownBitmapEncoder.cs
- ConstraintStruct.cs
- RecipientServiceModelSecurityTokenRequirement.cs
- FormatSettings.cs
- TitleStyle.cs
- StringBuilder.cs
- ConsoleKeyInfo.cs
- SignHashRequest.cs
- MetadataCache.cs
- CallbackWrapper.cs
- HotSpotCollectionEditor.cs
- WeakReferenceEnumerator.cs
- UrlPropertyAttribute.cs
- SelfIssuedAuthProofToken.cs
- DeleteMemberBinder.cs
- CompositionAdorner.cs
- PersonalizationState.cs
- listitem.cs
- DataGridCellsPanel.cs
- DateTimeSerializationSection.cs
- DrawingBrush.cs
- ProfilePropertySettingsCollection.cs
- DrawingServices.cs
- ScaleTransform3D.cs
- WebPartsPersonalization.cs
- ThreadPool.cs
- ParserOptions.cs
- WbemException.cs
- UInt64Storage.cs
- SqlServer2KCompatibilityAnnotation.cs