可直接复用。
1 using System; 2 using System.IO; 3 using System.Diagnostics; 4 using System.Windows.Forms; 5 6 namespace Utility 7 { 8 public class LogEventArgs : EventArgs 9 { 10 public int level; 11 public string category; 12 public string message; 13 14 public LogEventArgs(int _l, string _c, string _m) 15 { 16 level = _l; 17 category = _c; 18 message = _m; 19 } 20 } 21 /// <summary> 22 /// Debug log functionality 23 /// </summary> 24 public sealed class Log 25 { 26 static StreamWriter logWriter; 27 static string logPath; 28 static string logFilePath; 29 30 // a few standard values to facilitate logging 31 public struct Levels 32 { 33 public static readonly int Error = 0; 34 public static readonly int Warning = 2; 35 public static readonly int Debug = 5; 36 public static readonly int Verbose = 7; 37 }; 38 public static int Level; 39 40 /// <summary> 41 /// Static class (Only static members) 42 /// </summary> 43 private Log() 44 {} 45 46 static Log() 47 { 48 try 49 { 50 // start with a reasonable log level. 51 #if DEBUG 52 Level = 6; 53 #else 54 Level = 4; 55 #endif 56 logPath = DefaultSettingsDirectory(); 57 Directory.CreateDirectory(logPath); 58 59 // TODO: do not hardcode logfile name? 60 logFilePath = Path.Combine( logPath, "WorldWind.log" ); 61 62 logWriter = new StreamWriter(logFilePath, true); 63 logWriter.AutoFlush = true; 64 } 65 catch (Exception caught) 66 { 67 throw new System.ApplicationException(String.Format("Unexpected logfile error: {0}", logFilePath), caught); 68 } 69 } 70 71 // Return the full default directory path to be used for storing settings files, 72 // which is also where logfiles will be stored. 73 public static string DefaultSettingsDirectory() 74 { 75 // Example for Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData): 76 // @"C:\Documents and Settings\<user>\Application Data" 77 return Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + DefaultSettingsDirectorySuffix(); 78 } 79 80 // Return the program-specifc part of the full default directory path to be used 81 // for storing settings files, which is also where logfiles will be stored. 82 public static string DefaultSettingsDirectorySuffix() 83 { 84 // Application.ProductName is set by AssemblyProduct in \WorldWind\AssembyInfo.cs 85 Version ver = new Version(Application.ProductVersion); 86 return string.Format(@"\{0}\{1}\{2}.{3}.{4}.{5}", Application.CompanyName, Application.ProductName, ver.Major, ver.Minor, ver.Build, ver.Revision); 87 } 88 89 public static void Write(string category, string message) 90 { 91 Write(Levels.Error, category, message); 92 } 93 94 public static void Write(string message) 95 { 96 Write(Levels.Error, message); 97 } 98 99 /// <summary> 100 /// Logs a message to the system log. All messages trigger LogEvents, but only messages with level <= Log.Level are recorded to the log file. 101 /// </summary> 102 /// <param name="level">Log level. 0 (highest) .. 9 (lowest). See Log.Level for filtering</param> 103 /// <param name="category">1 to 4 character long tag for categorizing the log entries. 104 /// If the category is longer than 4 characters it will be clipped.</param> 105 /// <param name="message">The actual log messages to be written.</param> 106 public static void Write(int level, string category, string message) 107 { 108 if (level <= Log.Level) 109 { 110 try 111 { 112 lock (logWriter) 113 { 114 string logLine = string.Format("{0} {1} {2} {3}", 115 DateTime.Now.ToString("u"), 116 level, 117 category.PadRight(4, ' ').Substring(0, 4), 118 message); 119 120 #if DEBUG 121 System.Diagnostics.Debug.WriteLine( 122 string.Format("World Wind"+ 123 //".{0} [{1}]"+ 124 ": {2} {3} {4}", 125 System.Threading.Thread.CurrentThread.Name, 126 System.Threading.Thread.CurrentThread.ManagedThreadId, 127 level, 128 category.PadRight(4, ' ').Substring(0, 4), 129 message)); 130 #endif 131 logWriter.WriteLine(logLine); 132 } 133 } 134 catch (Exception caught) 135 { 136 throw new System.ApplicationException(String.Format("Unexpected logging error on write(1)"), caught); 137 } 138 } 139 } 140 141 /// <summary> 142 /// Logs a message to the system log only in debug builds. 143 /// </summary> 144 /// <param name="category">1 to 4 character long tag for categorizing the log entries. 145 /// If the category is longer than 4 characters it will be clipped.</param> 146 /// <param name="message">The actual log messages to be written.</param> 147 [Conditional("DEBUG")] 148 public static void DebugWrite( string category, string message ) 149 { 150 Debug.Write( category, message ); 151 } 152 153 /// <summary> 154 /// Logs a message to the system log 155 /// </summary> 156 public static void Write(int level, string message) 157 { 158 Write(level, "", message); 159 } 160 161 /// <summary> 162 /// Logs a message to the system log only in debug builds. 163 /// </summary> 164 [Conditional("DEBUG")] 165 public static void DebugWrite( int level, string message ) 166 { 167 Write(level, "", message); 168 } 169 170 /// <summary> 171 /// Writes a log of an exception. 172 /// </summary> 173 /// <param name="caught"></param> 174 public static void Write( Exception caught ) 175 { 176 try 177 { 178 if (caught is System.Threading.ThreadAbortException) 179 return; 180 181 lock (logWriter) 182 { 183 string functionName = "Unknown"; 184 string[] stacktrace = null; 185 if (caught.StackTrace != null) 186 { 187 stacktrace = caught.StackTrace.Split('\n'); 188 string firstStackTraceLine = stacktrace[0]; 189 functionName = firstStackTraceLine.Trim().Split(" (".ToCharArray())[1]; 190 } 191 string logFileName = string.Format("DEBUG_{0}.txt", DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss-ffff")); 192 string logFullPath = Path.Combine(logPath, logFileName); 193 using (StreamWriter sw = new StreamWriter(logFullPath, false)) 194 { 195 sw.WriteLine(caught.ToString()); 196 } 197 198 Write(Log.Levels.Error, "caught exception: "); 199 Write(Log.Levels.Error, caught.ToString()); 200 foreach (string line in stacktrace) 201 Write(Log.Levels.Debug, line); 202 } 203 } 204 catch (Exception caught2) 205 { 206 throw new System.ApplicationException(String.Format("{0}\nUnexpected logging error on write(2)", caught.Message), caught2); 207 } 208 } 209 210 /// <summary> 211 /// Writes a debug log of an exception. 212 /// Only executed in debug builds. 213 /// </summary> 214 [Conditional("DEBUG")] 215 public static void DebugWrite( Exception caught ) 216 { 217 try 218 { 219 if (caught is System.Threading.ThreadAbortException) 220 return; 221 222 string functionName = "Unknown"; 223 if(caught.StackTrace != null) 224 { 225 string firstStackTraceLine = caught.StackTrace.Split('\n')[0]; 226 functionName = firstStackTraceLine.Trim().Split(" (".ToCharArray())[1]; 227 } 228 string logFileName = string.Format("DEBUG_{0}.txt", DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss") ); 229 string logFullPath = Path.Combine(logPath, logFileName); 230 using (StreamWriter sw = new StreamWriter(logFullPath, false)) 231 { 232 sw.WriteLine(caught.ToString()); 233 } 234 } 235 catch (Exception caught2) 236 { 237 throw new System.ApplicationException(String.Format("{0}\nUnexpected logging error on write(3)", caught.Message), caught2); 238 } 239 } 240 } 241 }