TextWriterTraceListener.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / CompMod / System / Diagnostics / TextWriterTraceListener.cs / 1 / TextWriterTraceListener.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

/* 
 */ 
namespace System.Diagnostics {
    using System; 
    using System.IO;
    using System.Text;
    using System.Security.Permissions;
    using System.Runtime.InteropServices; 
    using System.IO.Ports;
    using Microsoft.Win32; 
    using System.Runtime.Versioning; 

    ///  
    ///    Directs tracing or debugging output to
    ///       a  or to a ,
    ///       such as  or .
    ///  
    [HostProtection(Synchronization=true)]
    public class TextWriterTraceListener : TraceListener { 
        internal TextWriter writer; 
        String fileName = null;
 
        /// 
        /// Initializes a new instance of the  class with
        /// 
        /// as the output recipient. 
        /// 
        public TextWriterTraceListener() { 
        } 

        ///  
        /// Initializes a new instance of the  class, using the
        ///    stream as the recipient of the debugging and tracing output.
        /// 
        public TextWriterTraceListener(Stream stream) 
            : this(stream, string.Empty) {
        } 
 
        /// 
        /// Initializes a new instance of the  class with the 
        ///    specified name and using the stream as the recipient of the debugging and tracing output.
        /// 
        public TextWriterTraceListener(Stream stream, string name)
            : base(name) { 
            if (stream == null) throw new ArgumentNullException("stream");
            this.writer = new StreamWriter(stream); 
        } 

        ///  
        /// Initializes a new instance of the  class using the
        ///    specified writer as recipient of the tracing or debugging output.
        /// 
        public TextWriterTraceListener(TextWriter writer) 
            : this(writer, string.Empty) {
        } 
 
        /// 
        /// Initializes a new instance of the  class with the 
        ///    specified name and using the specified writer as recipient of the tracing or
        ///    debugging
        ///    output.
        ///  
        public TextWriterTraceListener(TextWriter writer, string name)
            : base(name) { 
            if (writer == null) throw new ArgumentNullException("writer"); 
            this.writer = writer;
        } 

        /// 
        ///    [To be supplied.]
        ///  
        [ResourceExposure(ResourceScope.Machine)]
        public TextWriterTraceListener(string fileName) { 
            this.fileName = fileName; 
        }
 
        /// 
        ///    [To be supplied.]
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        public TextWriterTraceListener(string fileName, string name) : base(name) {
            this.fileName = fileName; 
        } 

        ///  
        ///     Indicates the text writer that receives the tracing
        ///       or debugging output.
        /// 
        public TextWriter Writer { 
            get {
                EnsureWriter(); 
                return writer; 
            }
 
            set {
                writer = value;
            }
        } 

        ///  
        /// Closes the  so that it no longer 
        ///    receives tracing or debugging output.
        ///  
        public override void Close() {
            if (writer != null)
                writer.Close();
 
            writer = null;
        } 
 
        /// 
        ///  
        /// 
        protected override void Dispose(bool disposing) {
            if (disposing)
                this.Close(); 
        }
 
        ///  
        /// Flushes the output buffer for the .
        ///  
        public override void Flush() {
            if (!EnsureWriter()) return;
            writer.Flush();
        } 

        ///  
        ///    Writes a message 
        ///       to this instance's .
        ///  
        public override void Write(string message) {
            if (!EnsureWriter()) return;
            if (NeedIndent) WriteIndent();
            writer.Write(message); 
        }
 
        ///  
        ///    Writes a message
        ///       to this instance's  followed by a line terminator. The 
        ///       default line terminator is a carriage return followed by a line feed (\r\n).
        /// 
        public override void WriteLine(string message) {
            if (!EnsureWriter()) return; 
            if (NeedIndent) WriteIndent();
            writer.WriteLine(message); 
            NeedIndent = true; 
        }
 
        private static Encoding GetEncodingWithFallback(Encoding encoding)
        {
            // Clone it and set the "?" replacement fallback
            Encoding fallbackEncoding = (Encoding)encoding.Clone(); 
            fallbackEncoding.EncoderFallback = EncoderFallback.ReplacementFallback;
            fallbackEncoding.DecoderFallback = DecoderFallback.ReplacementFallback; 
 
            return fallbackEncoding;
        } 

        // This uses a machine resource, scoped by the fileName variable.
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        internal bool EnsureWriter() {
            bool ret = true; 
 
            if (writer == null) {
                ret = false; 

                if (fileName == null)
                    return ret;
 
                // StreamWriter by default uses UTF8Encoding which will throw on invalid encoding errors.
                // This can cause the internal StreamWriter's state to be irrecoverable. It is bad for tracing 
                // APIs to throw on encoding errors. Instead, we should provide a "?" replacement fallback 
                // encoding to substitute illegal chars. For ex, In case of high surrogate character
                // D800-DBFF without a following low surrogate character DC00-DFFF 
                // NOTE: We also need to use an encoding that does't emit BOM whic is StreamWriter's default
                Encoding noBOMwithFallback = GetEncodingWithFallback(new UTF8Encoding(false));

 
                // To support multiple appdomains/instances tracing to the same file,
                // we will try to open the given file for append but if we encounter 
                // IO errors, we will prefix the file name with a unique GUID value 
                // and try one more time
                string fullPath = Path.GetFullPath(fileName); 
                string dirPath = Path.GetDirectoryName(fullPath);
                string fileNameOnly = Path.GetFileName(fullPath);

                for (int i=0; i<2; i++) { 
                    try {
                        writer = new StreamWriter(fullPath, true, noBOMwithFallback, 4096); 
                        ret = true; 
                        break;
                    } 
                    catch (IOException ) {

                        // Should we do this only for ERROR_SHARING_VIOLATION?
                        //if (InternalResources.MakeErrorCodeFromHR(Marshal.GetHRForException(ioexc)) == InternalResources.ERROR_SHARING_VIOLATION) { 

                        fileNameOnly = Guid.NewGuid().ToString() + fileNameOnly; 
                        fullPath = Path.Combine(dirPath, fileNameOnly); 
                        continue;
                    } 
                    catch (UnauthorizedAccessException ) {
                        //ERROR_ACCESS_DENIED, mostly ACL issues
                        break;
                    } 
                    catch (Exception ) {
                        break; 
                    } 
                }
 
                if (!ret) {
                    // Disable tracing to this listener. Every Write will be nop.
                    // We need to think of a central way to deal with the listener
                    // init errors in the future. The default should be that we eat 
                    // up any errors from listener and optionally notify the user
                    fileName = null; 
                } 
            }
            return ret; 
        }

    }
} 

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

/* 
 */ 
namespace System.Diagnostics {
    using System; 
    using System.IO;
    using System.Text;
    using System.Security.Permissions;
    using System.Runtime.InteropServices; 
    using System.IO.Ports;
    using Microsoft.Win32; 
    using System.Runtime.Versioning; 

    ///  
    ///    Directs tracing or debugging output to
    ///       a  or to a ,
    ///       such as  or .
    ///  
    [HostProtection(Synchronization=true)]
    public class TextWriterTraceListener : TraceListener { 
        internal TextWriter writer; 
        String fileName = null;
 
        /// 
        /// Initializes a new instance of the  class with
        /// 
        /// as the output recipient. 
        /// 
        public TextWriterTraceListener() { 
        } 

        ///  
        /// Initializes a new instance of the  class, using the
        ///    stream as the recipient of the debugging and tracing output.
        /// 
        public TextWriterTraceListener(Stream stream) 
            : this(stream, string.Empty) {
        } 
 
        /// 
        /// Initializes a new instance of the  class with the 
        ///    specified name and using the stream as the recipient of the debugging and tracing output.
        /// 
        public TextWriterTraceListener(Stream stream, string name)
            : base(name) { 
            if (stream == null) throw new ArgumentNullException("stream");
            this.writer = new StreamWriter(stream); 
        } 

        ///  
        /// Initializes a new instance of the  class using the
        ///    specified writer as recipient of the tracing or debugging output.
        /// 
        public TextWriterTraceListener(TextWriter writer) 
            : this(writer, string.Empty) {
        } 
 
        /// 
        /// Initializes a new instance of the  class with the 
        ///    specified name and using the specified writer as recipient of the tracing or
        ///    debugging
        ///    output.
        ///  
        public TextWriterTraceListener(TextWriter writer, string name)
            : base(name) { 
            if (writer == null) throw new ArgumentNullException("writer"); 
            this.writer = writer;
        } 

        /// 
        ///    [To be supplied.]
        ///  
        [ResourceExposure(ResourceScope.Machine)]
        public TextWriterTraceListener(string fileName) { 
            this.fileName = fileName; 
        }
 
        /// 
        ///    [To be supplied.]
        /// 
        [ResourceExposure(ResourceScope.Machine)] 
        public TextWriterTraceListener(string fileName, string name) : base(name) {
            this.fileName = fileName; 
        } 

        ///  
        ///     Indicates the text writer that receives the tracing
        ///       or debugging output.
        /// 
        public TextWriter Writer { 
            get {
                EnsureWriter(); 
                return writer; 
            }
 
            set {
                writer = value;
            }
        } 

        ///  
        /// Closes the  so that it no longer 
        ///    receives tracing or debugging output.
        ///  
        public override void Close() {
            if (writer != null)
                writer.Close();
 
            writer = null;
        } 
 
        /// 
        ///  
        /// 
        protected override void Dispose(bool disposing) {
            if (disposing)
                this.Close(); 
        }
 
        ///  
        /// Flushes the output buffer for the .
        ///  
        public override void Flush() {
            if (!EnsureWriter()) return;
            writer.Flush();
        } 

        ///  
        ///    Writes a message 
        ///       to this instance's .
        ///  
        public override void Write(string message) {
            if (!EnsureWriter()) return;
            if (NeedIndent) WriteIndent();
            writer.Write(message); 
        }
 
        ///  
        ///    Writes a message
        ///       to this instance's  followed by a line terminator. The 
        ///       default line terminator is a carriage return followed by a line feed (\r\n).
        /// 
        public override void WriteLine(string message) {
            if (!EnsureWriter()) return; 
            if (NeedIndent) WriteIndent();
            writer.WriteLine(message); 
            NeedIndent = true; 
        }
 
        private static Encoding GetEncodingWithFallback(Encoding encoding)
        {
            // Clone it and set the "?" replacement fallback
            Encoding fallbackEncoding = (Encoding)encoding.Clone(); 
            fallbackEncoding.EncoderFallback = EncoderFallback.ReplacementFallback;
            fallbackEncoding.DecoderFallback = DecoderFallback.ReplacementFallback; 
 
            return fallbackEncoding;
        } 

        // This uses a machine resource, scoped by the fileName variable.
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        internal bool EnsureWriter() {
            bool ret = true; 
 
            if (writer == null) {
                ret = false; 

                if (fileName == null)
                    return ret;
 
                // StreamWriter by default uses UTF8Encoding which will throw on invalid encoding errors.
                // This can cause the internal StreamWriter's state to be irrecoverable. It is bad for tracing 
                // APIs to throw on encoding errors. Instead, we should provide a "?" replacement fallback 
                // encoding to substitute illegal chars. For ex, In case of high surrogate character
                // D800-DBFF without a following low surrogate character DC00-DFFF 
                // NOTE: We also need to use an encoding that does't emit BOM whic is StreamWriter's default
                Encoding noBOMwithFallback = GetEncodingWithFallback(new UTF8Encoding(false));

 
                // To support multiple appdomains/instances tracing to the same file,
                // we will try to open the given file for append but if we encounter 
                // IO errors, we will prefix the file name with a unique GUID value 
                // and try one more time
                string fullPath = Path.GetFullPath(fileName); 
                string dirPath = Path.GetDirectoryName(fullPath);
                string fileNameOnly = Path.GetFileName(fullPath);

                for (int i=0; i<2; i++) { 
                    try {
                        writer = new StreamWriter(fullPath, true, noBOMwithFallback, 4096); 
                        ret = true; 
                        break;
                    } 
                    catch (IOException ) {

                        // Should we do this only for ERROR_SHARING_VIOLATION?
                        //if (InternalResources.MakeErrorCodeFromHR(Marshal.GetHRForException(ioexc)) == InternalResources.ERROR_SHARING_VIOLATION) { 

                        fileNameOnly = Guid.NewGuid().ToString() + fileNameOnly; 
                        fullPath = Path.Combine(dirPath, fileNameOnly); 
                        continue;
                    } 
                    catch (UnauthorizedAccessException ) {
                        //ERROR_ACCESS_DENIED, mostly ACL issues
                        break;
                    } 
                    catch (Exception ) {
                        break; 
                    } 
                }
 
                if (!ret) {
                    // Disable tracing to this listener. Every Write will be nop.
                    // We need to think of a central way to deal with the listener
                    // init errors in the future. The default should be that we eat 
                    // up any errors from listener and optionally notify the user
                    fileName = null; 
                } 
            }
            return ret; 
        }

    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

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