MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4#define TRACE5 6using System.Collections.Generic;7using System.Collections.Specialized;8using System.Diagnostics;9using System.Globalization;10using System.IO;11using System.Reflection;12using System.Text;13using System.Threading;14 15namespace System.Management.Automation16{17 #region PSTraceSourceOptions18 /// <summary>19 /// These flags enable tracing based on the types of20 /// a tracing supplied. Each type of tracing will allow21 /// for one or more methods in the StructuredTraceSource class to become22 /// "enabled".23 /// </summary>24 [Flags]25 public enum PSTraceSourceOptions26 {27 /// <summary>28 /// All tracing off.29 /// </summary>30 /// <!--31 /// No tracing is enabled32 /// -->33 None = 0x00000000,34 35 /// <summary>36 /// Constructors will be traced.37 /// </summary>38 /// <!--39 /// The TraceConstructor methods are enabled40 /// -->41 Constructor = 0x00000001,42 43 /// <summary>44 /// Dispose will be traced.45 /// </summary>46 /// <!--47 /// The TraceDispose methods are enabled48 /// -->49 Dispose = 0x00000002,50 51 /// <summary>52 /// Finalize will be traced.53 /// </summary>54 /// <!--55 /// The TraceFinalizer methods are enabled56 /// -->57 Finalizer = 0x00000004,58 59 /// <summary>60 /// Methods will be traced.61 /// </summary>62 /// <!--63 /// The TraceMethod methods are enabled64 /// -->65 Method = 0x00000008,66 67 /// <summary>68 /// Properties will be traced.69 /// </summary>70 /// <!--71 /// The TraceProperty methods are enabled72 /// -->73 Property = 0x00000010,74 75 /// <summary>76 /// Delegates will be traced.77 /// </summary>78 /// <!--79 /// The TraceDelegate and TraceDelegateHandler methods are enabled80 /// -->81 Delegates = 0x00000020,82 83 /// <summary>84 /// Events will be traced.85 /// </summary>86 /// <!--87 /// The TraceRaiseEvent and TraceEventHandler methods are enabled88 /// -->89 Events = 0x00000040,90 91 /// <summary>92 /// Exceptions will be traced.93 /// </summary>94 /// <!--95 /// The TraceException method is enabled96 /// -->97 Exception = 0x00000080,98 99 /// <summary>100 /// Locks will be traced.101 /// </summary>102 /// <!--103 /// The TraceLock methods are enabled104 /// -->105 Lock = 0x00000100,106 107 /// <summary>108 /// Errors will be traced.109 /// </summary>110 /// <!--111 /// The TraceError methods are enabled112 /// -->113 Error = 0x00000200,114 115 /// <summary>116 /// Warnings will be traced.117 /// </summary>118 /// <!--119 /// The TraceWarning methods are enabled120 /// -->121 Warning = 0x00000400,122 123 /// <summary>124 /// Verbose messages will be traced.125 /// </summary>126 Verbose = 0x00000800,127 128 /// <summary>129 /// WriteLines will be traced.130 /// </summary>131 /// <!--132 /// The WriteLine methods are enabled133 /// -->134 WriteLine = 0x00001000,135 136 /// <summary>137 /// TraceScope calls will be traced.138 /// </summary>139 Scope = 0x00002000,140 141 /// <summary>142 /// Assertions will be traced.143 /// </summary>144 Assert = 0x00004000,145 146 /// <summary>147 /// A combination of flags that trace the execution flow.148 /// The methods associated with the flags; Constructor, Dispose,149 /// Finalizer, Method, Delegates, and Events will be enabled.150 /// </summary>151 ExecutionFlow =152 Constructor |153 Dispose |154 Finalizer |155 Method |156 Delegates |157 Events |158 Scope,159 160 /// <summary>161 /// A combination of flags that trace the data.162 /// The methods associated with the flags; Constructor, Dispose,163 /// Finalizer, Property, and WriteLine will be enabled.164 /// </summary>165 Data =166 Constructor |167 Dispose |168 Finalizer |169 Property |170 Verbose |171 WriteLine,172 173 /// <summary>174 /// A combination of flags that trace the errors.175 /// The methods associated with the flags; Error,176 /// and Exception will be enabled.177 /// </summary>178 Errors =179 Error |180 Exception,181 182 /// <summary>183 /// All combination of trace flags will be set.184 /// All methods for tracing will be enabled.185 /// </summary>186 All =187 Constructor |188 Dispose |189 Finalizer |190 Method |191 Property |192 Delegates |193 Events |194 Exception |195 Error |196 Warning |197 Verbose |198 Lock |199 WriteLine |200 Scope |201 Assert202 }203 204 #endregion PSTraceSourceOptions205 206 /// <summary>207 /// An PSTraceSource is a representation of a System.Diagnostics.TraceSource instance208 /// that is used in the PowerShell components to produce trace output.209 /// </summary>210 /// <!--211 /// The StructuredTraceSource class is derived from TraceSource to provide granular212 /// control over the tracing in a program. An instance of StructuredTraceSource213 /// is created for each category of tracing such that separate flags214 /// (filters) can be set. Each flag enables one or more method for tracing.215 ///216 /// For instance, the Exception flag will enable tracing on these methods:217 /// TraceException.218 /// </summary>219 /// <remarks>220 /// To get an instance of this class a user should define a static221 /// field of the type StructuredTraceSource, and assign the results of GetTracer() to it.222 /// If the category should be automatically put in the application config file the223 /// field should be decorated with the TraceSourceAttribute so that GenerateAppConfigFile.exe224 /// can find it through reflection.225 /// <example>226 /// <code>227 /// [TraceSourceAttribute("category", "description")]228 /// public static StructuredTraceSource tracer = GetTracer("category", "description", true);229 /// </code>230 /// </example>231 /// Other than initial creation of this class through the GetTracer method,232 /// this class should throw no exceptions. Any call to a StructuredTraceSource method233 /// that results in an exception being thrown will be ignored.234 /// -->235 public partial class PSTraceSource236 {237 #region PSTraceSource construction methods238 239 /// <summary>240 /// Constructor that determines the name of the trace241 /// flag in the config file.242 /// </summary>243 /// <param name="fullName">244 /// The full name for the trace category. This is different from the name parameter as245 /// it is not limited to 16 characters.246 /// </param>247 /// <param name="name">248 /// The name of the category that this class249 /// will control the tracing for. This parameter must always be 16 characters to ensure250 /// proper formatting of the output.251 /// </param>252 /// <param name="description">253 /// The description to describe what the category254 /// is used for.255 /// </param>256 /// <param name="traceHeaders">257 /// If true, the line headers will be traced, if false, only the trace message will be traced.258 /// </param>259 internal PSTraceSource(string fullName, string name, string description, bool traceHeaders)260 {261 ArgumentException.ThrowIfNullOrEmpty(fullName);262 263 try264 {265 FullName = fullName;266 _name = name;267 268 // TODO: move this to startup json file instead of using env var269 string tracingEnvVar = Environment.GetEnvironmentVariable("MshEnableTrace");270 271 if (string.Equals(272 tracingEnvVar,273 "True",274 StringComparison.OrdinalIgnoreCase))275 {276 string options = this.TraceSource.Attributes["Options"];277 if (options != null)278 {279 _flags = (PSTraceSourceOptions)Enum.Parse(typeof(PSTraceSourceOptions), options, true);280 }281 }282 283 ShowHeaders = traceHeaders;284 Description = description;285 }286 catch (System.Xml.XmlException)287 {288 // This exception occurs when the config289 // file is malformed. Just default to Off.290 291 _flags = PSTraceSourceOptions.None;292 }293#if !CORECLR294 catch (System.Configuration.ConfigurationException)295 {296 // This exception occurs when the config297 // file is malformed. Just default to Off.298 299 _flags = PSTraceSourceOptions.None;300 }301#endif302 }303 304 private static bool globalTraceInitialized;305 306 /// <summary>307 /// Traces the app domain header with information about the execution308 /// time, the platform, etc.309 /// </summary>310 internal void TraceGlobalAppDomainHeader()311 {312 // Only trace the global header if it hasn't313 // already been traced314 315 if (globalTraceInitialized)316 {317 return;318 }319 320 // AppDomain321 322 OutputLine(323 PSTraceSourceOptions.All,324 "Initializing tracing for AppDomain: {0}",325 AppDomain.CurrentDomain.FriendlyName);326 327 // Current time328 329 OutputLine(330 PSTraceSourceOptions.All,331 "\tCurrent time: {0}",332 DateTime.Now.ToString());333 334 // OS build335 336 OutputLine(337 PSTraceSourceOptions.All,338 "\tOS Build: {0}",339 Environment.OSVersion.ToString());340 341 // .NET Framework version342 343 OutputLine(344 PSTraceSourceOptions.All,345 "\tFramework Build: {0}\n",346 Environment.Version.ToString());347 348 // Mark that we have traced the global header349 350 globalTraceInitialized = true;351 }352 353 /// <summary>354 /// Outputs a header when a new StructuredTraceSource object is created.355 /// </summary>356 /// <param name="callingAssembly">357 /// The assembly that created the instance of the StructuredTraceSource.358 /// </param>359 /// <remarks>360 /// A header will be output that contains information such as;361 /// the category and description of the new trace object,362 /// the assembly in which the new trace object363 /// will be stored.364 /// </remarks>365 internal void TracerObjectHeader(366 Assembly callingAssembly)367 {368 if (_flags == PSTraceSourceOptions.None)369 {370 return;371 }372 373 // Write the header for the new trace object374 375 OutputLine(PSTraceSourceOptions.All, "Creating tracer:");376 377 // Category378 379 OutputLine(380 PSTraceSourceOptions.All,381 "\tCategory: {0}",382 this.Name);383 384 // Description385 386 OutputLine(387 PSTraceSourceOptions.All,388 "\tDescription: {0}",389 Description);390 391 if (callingAssembly != null)392 {393 // Assembly name394 395 OutputLine(396 PSTraceSourceOptions.All,397 "\tAssembly: {0}",398 callingAssembly.FullName);399 400 // Assembly location401 402 OutputLine(403 PSTraceSourceOptions.All,404 "\tAssembly Location: {0}",405 callingAssembly.Location);406 407 // Assembly File timestamp408 409 FileInfo assemblyFileInfo =410 new FileInfo(callingAssembly.Location);411 412 OutputLine(413 PSTraceSourceOptions.All,414 "\tAssembly File Timestamp: {0}",415 assemblyFileInfo.CreationTime.ToString());416 }417 418 StringBuilder flagBuilder = new StringBuilder();419 // Label420 421 flagBuilder.Append("\tFlags: ");422 flagBuilder.Append(_flags.ToString());423 424 // Write out the flags425 426 OutputLine(PSTraceSourceOptions.All, flagBuilder.ToString());427 }428 #endregion StructuredTraceSource constructor methods429 430 #region PSTraceSourceOptions.Scope431 432 internal IDisposable TraceScope(string msg)433 {434 if (_flags.HasFlag(PSTraceSourceOptions.Scope))435 {436 try437 {438 return new ScopeTracer(this, PSTraceSourceOptions.Scope, null, null, string.Empty, msg);439 }440 catch { }441 }442 443 return null;444 }445 446 internal IDisposable TraceScope(string format, object arg1)447 {448 if (_flags.HasFlag(PSTraceSourceOptions.Scope))449 {450 try451 {452 return new ScopeTracer(this, PSTraceSourceOptions.Scope, null, null, string.Empty, format, arg1);453 }454 catch { }455 }456 457 return null;458 }459 460 internal IDisposable TraceScope(string format, object arg1, object arg2)461 {462 if (_flags.HasFlag(PSTraceSourceOptions.Scope))463 {464 try465 {466 return new ScopeTracer(this, PSTraceSourceOptions.Scope, null, null, string.Empty, format, arg1, arg2);467 }468 catch { }469 }470 471 return null;472 }473 474 #endregion PSTraceSourceOptions.Scope475 476 #region PSTraceSourceOptions.Method methods/helpers477 /// <summary>478 /// Traces the method name and indents the trace output.479 /// </summary>480 /// <param name="format">481 /// The format string for additional arguments to be traced482 /// </param>483 /// <param name="args">484 /// The additional arguments given to the format string485 /// </param>486 /// <returns>487 /// An object that supports IDisposable. The caller488 /// should dispose of the object when it goes out of489 /// scope.490 /// </returns>491 /// <remarks>492 /// <newpara/>493 /// <example>494 /// <code>495 /// public void MethodName(int count)496 /// {497 /// using (TraceMethod(498 /// "count={0:d}",499 /// count))500 /// {501 /// // do something here...502 /// }503 /// }504 /// </code>505 /// </example>506 /// <newpara/>507 /// This will produce output similar to the following:508 /// <newpara/>509 /// Entering MethodName: count=4510 /// other trace output indented511 /// Leaving MethodName512 /// </remarks>513 internal IDisposable TraceMethod(514 string format,515 params object[] args)516 {517 if (_flags.HasFlag(PSTraceSourceOptions.Method))518 {519 try520 {521 // Get the name of the method that called this method522 // 1, signifies the caller of this method, whereas 2523 // would signify the caller of that method.524 525 string methodName = GetCallingMethodNameAndParameters(1);526 527 // Create the method tracer object528 return (IDisposable)new ScopeTracer(529 this,530 PSTraceSourceOptions.Method,531 methodOutputFormatter,532 methodLeavingFormatter,533 methodName,534 format,535 args);536 }537 catch538 {539 // Eat all exceptions540 541 // Do not assert here because exceptions can be542 // raised while a thread is shutting down during543 // normal operation.544 }545 }546 547 return null;548 }549 550 #endregion PSTraceSourceOptions.Method methods/helpers551 552 #region PSTraceSourceOptions.Events methods/helpers553 554 /// <summary>555 /// Traces the entrance and exit from event handlers.556 /// </summary>557 /// <returns>558 /// An object that supports IDisposable. The caller559 /// should dispose of the object when it goes out of560 /// scope.561 /// </returns>562 internal IDisposable TraceEventHandlers()563 {564 if (_flags.HasFlag(PSTraceSourceOptions.Events))565 {566 try567 {568 // Get the name of the method that called this method569 // 1, signifies the caller of this method, whereas 2570 // would signify the caller of that method.571 572 string methodName = GetCallingMethodNameAndParameters(1);573 574 // Create the scope tracer object575 return (IDisposable)new ScopeTracer(576 this,577 PSTraceSourceOptions.Events,578 eventHandlerOutputFormatter,579 eventHandlerLeavingFormatter,580 methodName,581 string.Empty);582 }583 catch584 {585 // Eat all exceptions586 587 // Do not assert here because exceptions can be588 // raised while a thread is shutting down during589 // normal operation.590 }591 }592 593 return null;594 }595 596 /// <summary>597 /// Traces the entrance and exit from event handlers.598 /// </summary>599 /// <param name="format">600 /// The format string for additional arguments to be traced601 /// </param>602 /// <param name="args">603 /// The additional arguments given to the format string604 /// </param>605 /// <returns>606 /// An object that supports IDisposable. The caller607 /// should dispose of the object when it goes out of608 /// scope.609 /// </returns>610 internal IDisposable TraceEventHandlers(611 string format,612 params object[] args)613 {614 if (_flags.HasFlag(PSTraceSourceOptions.Events))615 {616 try617 {618 // Get the name of the method that called this method619 // 1, signifies the caller of this method, whereas 2620 // would signify the caller of that method.621 622 string methodName = GetCallingMethodNameAndParameters(1);623 624 // Create the scope tracer object625 return (IDisposable)new ScopeTracer(626 this,627 PSTraceSourceOptions.Events,628 eventHandlerOutputFormatter,629 eventHandlerLeavingFormatter,630 methodName,631 format,632 args);633 }634 catch635 {636 // Eat all exceptions637 638 // Do not assert here because exceptions can be639 // raised while a thread is shutting down during640 // normal operation.641 }642 }643 644 return null;645 }646 #endregion PSTraceSourceOptions.Events methods/helpers647 648 #region PSTraceSourceOptions.Lock methods/helpers649 650 /// <summary>651 /// Traces the user specified lock name and indents the trace output.652 /// </summary>653 /// <returns>654 /// An object that supports IDisposable. The caller655 /// should dispose of the object when it goes out of656 /// scope.657 /// </returns>658 /// <remarks>659 /// <newpara/>660 /// <example>661 /// <code>662 /// public void MethodName()663 /// {664 /// lock (this)665 /// {666 /// using (TraceLock("my lock name"))667 /// {668 /// // do something here...669 /// }670 /// }671 /// }672 /// </code>673 /// </example>674 /// <newpara/>675 /// This will produce output similar to the following:676 /// <newpara/>677 /// Entering Lock: my lock name678 /// other trace output indented679 /// Leaving Lock: my lock name680 /// </remarks>681 internal IDisposable TraceLock(string lockName)682 {683 if (_flags.HasFlag(PSTraceSourceOptions.Lock))684 {685 try686 {687 return (IDisposable)new ScopeTracer(688 this,689 PSTraceSourceOptions.Lock,690 lockEnterFormatter,691 lockLeavingFormatter,692 lockName);693 }694 catch695 {696 // Eat all exceptions697 698 // Do not assert here because exceptions can be699 // raised while a thread is shutting down during700 // normal operation.701 }702 }703 704 return null;705 }706 707 /// <summary>708 /// Call this before acquiring a lock.709 /// </summary>710 /// <param name="lockName">711 /// User defined name given to the lock712 /// </param>713 internal void TraceLockAcquiring(string lockName)714 {715 if (_flags.HasFlag(PSTraceSourceOptions.Lock))716 {717 TraceLockHelper(718 lockAcquiringFormatter,719 lockName);720 }721 }722 723 /// <summary>724 /// Call this after acquiring a lock.725 /// </summary>726 /// <param name="lockName">727 /// User defined name given to the lock728 /// </param>729 /// <remarks>730 /// Use this only if the TraceLock that returns731 /// an IDisposable won't work in your situation.732 /// You will not get automatic indentation or733 /// release tracing of the lock.734 /// </remarks>735 internal void TraceLockAcquired(string lockName)736 {737 if (_flags.HasFlag(PSTraceSourceOptions.Lock))738 {739 TraceLockHelper(740 lockEnterFormatter,741 lockName);742 }743 }744 745 /// <summary>746 /// Call this after releasing the lock, but only747 /// if you called TraceLockAcquired when you acquired748 /// the lock.749 /// </summary>750 /// <param name="lockName">751 /// User defined name given to the lock752 /// </param>753 internal void TraceLockReleased(string lockName)754 {755 if (_flags.HasFlag(PSTraceSourceOptions.Lock))756 {757 TraceLockHelper(758 lockLeavingFormatter,759 lockName);760 }761 }762 763 /// <summary>764 /// A helper to simplify tracing of the lock flags.765 /// </summary>766 /// <param name="formatter">767 /// A format string for the output.768 /// </param>769 /// <param name="lockName">770 /// User defined name for the lock771 /// </param>772 private void TraceLockHelper(773 string formatter,774 string lockName)775 {776 try777 {778 OutputLine(779 PSTraceSourceOptions.Lock,780 formatter,781 lockName);782 }783 catch784 {785 // Eat all exceptions786 787 // Do not assert here because exceptions can be788 // raised while a thread is shutting down during789 // normal operation.790 }791 }792 #endregion PSTraceSourceOptions.Lock methods/helpers793 794 #region PSTraceSourceOptions.Error,Warning,Normal methods/helpers795 /// <summary>796 /// Traces the specified formatted output when PSTraceSourceOptions.Error797 /// is enabled.798 /// </summary>799 /// <param name="errorMessageFormat">800 /// The format string containing the error message801 /// </param>802 /// <param name="args">803 /// The arguments for the format string804 /// </param>805 internal void TraceError(806 string errorMessageFormat,807 params object[] args)808 {809 if (_flags.HasFlag(PSTraceSourceOptions.Error))810 {811 FormatOutputLine(812 PSTraceSourceOptions.Error,813 errorFormatter,814 errorMessageFormat,815 args);816 }817 }818 819 /// <summary>820 /// Traces the specified formatted output when PSTraceSourceOptions.Warning821 /// is enabled.822 /// </summary>823 /// <param name="warningMessageFormat">824 /// The format string containing the error message825 /// </param>826 /// <param name="args">827 /// The arguments for the format string828 /// </param>829 internal void TraceWarning(830 string warningMessageFormat,831 params object[] args)832 {833 if (_flags.HasFlag(PSTraceSourceOptions.Warning))834 {835 FormatOutputLine(836 PSTraceSourceOptions.Warning,837 warningFormatter,838 warningMessageFormat,839 args);840 }841 }842 843 /// <summary>844 /// Traces the specified formatted output when PSTraceSourceOptions.Verbose845 /// is enabled.846 /// </summary>847 /// <param name="verboseMessageFormat">848 /// The format string containing the error message849 /// </param>850 /// <param name="args">851 /// The arguments for the format string852 /// </param>853 internal void TraceVerbose(854 string verboseMessageFormat,855 params object[] args)856 {857 if (_flags.HasFlag(PSTraceSourceOptions.Verbose))858 {859 FormatOutputLine(860 PSTraceSourceOptions.Verbose,861 verboseFormatter,862 verboseMessageFormat,863 args);864 }865 }866 867 /// <summary>868 /// Traces the formatted output when PSTraceSourceOptions.WriteLine is enabled.869 /// </summary>870 /// <param name="format">871 /// The format string872 /// </param>873 internal void WriteLine(string format)874 {875 if (_flags.HasFlag(PSTraceSourceOptions.WriteLine))876 {877 FormatOutputLine(878 PSTraceSourceOptions.WriteLine,879 writeLineFormatter,880 format,881 Array.Empty<object>());882 }883 }884 885 /// <summary>886 /// Traces the formatted output when PSTraceSourceOptions.WriteLine is enabled.887 /// </summary>888 /// <param name="format">The format string.</param>889 /// <param name="arg1"></param>890 internal void WriteLine(string format, object arg1)891 {892 if (_flags.HasFlag(PSTraceSourceOptions.WriteLine))893 {894 FormatOutputLine(895 PSTraceSourceOptions.WriteLine,896 writeLineFormatter,897 format,898 new object[] { arg1 });899 }900 }901 902 internal void WriteLine(string format, bool arg1)903 {904 WriteLine(format, (object)arg1.ToString());905 }906 907 internal void WriteLine(string format, byte arg1)908 {909 WriteLine(format, (object)arg1.ToString());910 }911 912 internal void WriteLine(string format, char arg1)913 {914 WriteLine(format, (object)arg1.ToString());915 }916 917 internal void WriteLine(string format, decimal arg1)918 {919 WriteLine(format, (object)arg1.ToString());920 }921 922 internal void WriteLine(string format, double arg1)923 {924 WriteLine(format, (object)arg1.ToString());925 }926 927 internal void WriteLine(string format, float arg1)928 {929 WriteLine(format, (object)arg1.ToString());930 }931 932 internal void WriteLine(string format, int arg1)933 {934 WriteLine(format, (object)arg1.ToString());935 }936 937 internal void WriteLine(string format, long arg1)938 {939 WriteLine(format, (object)arg1.ToString());940 }941 942 internal void WriteLine(string format, uint arg1)943 {944 WriteLine(format, (object)arg1.ToString());945 }946 947 internal void WriteLine(string format, ulong arg1)948 {949 WriteLine(format, (object)arg1.ToString());950 }951 952 /// <summary>953 /// Traces the formatted output when PSTraceSourceOptions.WriteLine is enabled.954 /// </summary>955 /// <param name="format">The format string.</param>956 /// <param name="arg1"></param>957 /// <param name="arg2"></param>958 internal void WriteLine(string format, object arg1, object arg2)959 {960 if (_flags.HasFlag(PSTraceSourceOptions.WriteLine))961 {962 FormatOutputLine(963 PSTraceSourceOptions.WriteLine,964 writeLineFormatter,965 format,966 new object[] { arg1, arg2 });967 }968 }969 970 /// <summary>971 /// Traces the formatted output when PSTraceSourceOptions.WriteLine is enabled.972 /// </summary>973 /// <param name="format">The format string.</param>974 /// <param name="arg1"></param>975 /// <param name="arg2"></param>976 /// <param name="arg3"></param>977 internal void WriteLine(string format, object arg1, object arg2, object arg3)978 {979 if (_flags.HasFlag(PSTraceSourceOptions.WriteLine))980 {981 FormatOutputLine(982 PSTraceSourceOptions.WriteLine,983 writeLineFormatter,984 format,985 new object[] { arg1, arg2, arg3 });986 }987 }988 989 /// <summary>990 /// Traces the formatted output when PSTraceSourceOptions.WriteLine is enabled.991 /// </summary>992 /// <param name="format">The format string.</param>993 /// <param name="arg1"></param>994 /// <param name="arg2"></param>995 /// <param name="arg3"></param>996 /// <param name="arg4"></param>997 internal void WriteLine(string format, object arg1, object arg2, object arg3, object arg4)998 {999 if (_flags.HasFlag(PSTraceSourceOptions.WriteLine))1000 {1001 FormatOutputLine(1002 PSTraceSourceOptions.WriteLine,1003 writeLineFormatter,1004 format,1005 new object[] { arg1, arg2, arg3, arg4 });1006 }1007 }1008 1009 /// <summary>1010 /// Traces the formatted output when PSTraceSourceOptions.WriteLine is enabled.1011 /// </summary>1012 /// <param name="format">The format string.</param>1013 /// <param name="arg1"></param>1014 /// <param name="arg2"></param>1015 /// <param name="arg3"></param>1016 /// <param name="arg4"></param>1017 /// <param name="arg5"></param>1018 internal void WriteLine(string format, object arg1, object arg2, object arg3, object arg4, object arg5)1019 {1020 if (_flags.HasFlag(PSTraceSourceOptions.WriteLine))1021 {1022 FormatOutputLine(1023 PSTraceSourceOptions.WriteLine,1024 writeLineFormatter,1025 format,1026 new object[] { arg1, arg2, arg3, arg4, arg5 });1027 }1028 }1029 1030 /// <summary>1031 /// Traces the formatted output when PSTraceSourceOptions.WriteLine is enabled.1032 /// </summary>1033 /// <param name="format">The format string.</param>1034 /// <param name="arg1"></param>1035 /// <param name="arg2"></param>1036 /// <param name="arg3"></param>1037 /// <param name="arg4"></param>1038 /// <param name="arg5"></param>1039 /// <param name="arg6"></param>1040 internal void WriteLine(string format, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6)1041 {1042 if (_flags.HasFlag(PSTraceSourceOptions.WriteLine))1043 {1044 FormatOutputLine(1045 PSTraceSourceOptions.WriteLine,1046 writeLineFormatter,1047 format,1048 new object[] { arg1, arg2, arg3, arg4, arg5, arg6 });1049 }1050 }1051 1052 /// <summary>1053 /// Traces the formatted output when PSTraceSourceOptions.WriteLine is enabled.1054 /// </summary>1055 /// <param name="arg">1056 /// The object to be output1057 /// </param>1058 internal void WriteLine(object arg)1059 {1060 if (_flags.HasFlag(PSTraceSourceOptions.WriteLine))1061 {1062 WriteLine("{0}", arg == null ? "null" : arg.ToString());1063 }1064 }1065 1066 /// <summary>1067 /// Formats the specified text and then traces it.1068 /// </summary>1069 /// <param name="flag">1070 /// The flag that met the criteria to have this line traced.1071 /// </param>1072 /// <param name="classFormatter">1073 /// This is the trace class formatter. For instance,1074 /// TraceError has a formatter like "ERROR: {0}".1075 /// </param>1076 /// <param name="format">1077 /// Additional format string.1078 /// </param>1079 /// <param name="args">1080 /// Arguments for the additional format string1081 /// </param>1082 private void FormatOutputLine(1083 PSTraceSourceOptions flag,1084 string classFormatter,1085 string format,1086 params object[] args)1087 {1088 try1089 {1090 // First format the class format string and the1091 // user provided format string together1092 StringBuilder output = new StringBuilder();1093 1094 if (classFormatter != null)1095 {1096 output.Append(classFormatter);1097 }1098 1099 if (format != null)1100 {1101 output.AppendFormat(1102 CultureInfo.CurrentCulture,1103 format,1104 args);1105 }1106 1107 // finally trace the output1108 OutputLine(flag, output.ToString());1109 }1110 catch1111 {1112 // Eat all exceptions1113 //1114 // Do not assert here because exceptions can be1115 // raised while a thread is shutting down during1116 // normal operation.1117 }1118 }1119 1120 #endregion PSTraceSourceOptions.Error methods/helpers1121 1122 #region Class helper methods and properties1123 1124 /// <summary>1125 /// Gets the method name of the method that called this one1126 /// plus the skipFrames.1127 /// </summary>1128 /// <remarks>1129 /// For instance, GetCallingMethodNameAndParameters(1)1130 /// will return the method that called the method that is calling1131 /// GetCallingMethodNameAndParameters.1132 /// </remarks>1133 /// <param name="skipFrames">1134 /// The number of frames to skip in the calling stack.1135 /// </param>1136 /// <returns>1137 /// The name of the method on the stack.1138 /// </returns>1139 private static string GetCallingMethodNameAndParameters(int skipFrames)1140 {1141 StringBuilder methodAndParameters = null;1142 1143 try1144 {1145 // Use the stack to get the method and type information1146 // for the calling method1147 1148 StackFrame stackFrame = new StackFrame(++skipFrames);1149 MethodBase callingMethod = stackFrame.GetMethod();1150 1151 Type declaringType = callingMethod.DeclaringType;1152 1153 // Append the class name and method name together1154 1155 methodAndParameters = new StringBuilder();1156 1157 // Note: don't use the FullName for the declaringType1158 // as it is usually way too long and makes the trace1159 // output hard to read.1160 1161 methodAndParameters.AppendFormat(1162 CultureInfo.CurrentCulture,1163 "{0}.{1}(",1164 declaringType.Name,1165 callingMethod.Name);1166 1167 methodAndParameters.Append(')');1168 }1169 catch1170 {1171 // Eat all exceptions1172 1173 // Do not assert here because exceptions can be1174 // raised while a thread is shutting down during1175 // normal operation.1176 }1177 1178 return methodAndParameters.ToString();1179 }1180 1181 // The default formatter for TraceError1182 private const string errorFormatter =1183 "ERROR: ";1184 1185 // The default formatter for TraceWarning1186 private const string warningFormatter =1187 "Warning: ";1188 1189 // The default formatter for TraceVerbose1190 private const string verboseFormatter =1191 "Verbose: ";1192 1193 // The default formatter for WriteLine1194 private const string writeLineFormatter =1195 "";1196 1197 // The default formatter for TraceConstructor1198 1199 private const string constructorOutputFormatter =1200 "Enter Ctor {0}";