| File: ExceptionHandling.cs | Web Access |
| Project: src\msbuild\src\Framework\Microsoft.Build.Framework.csproj (Microsoft.Build.Framework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Serialization; using System.Security; using System.Threading; using System.Xml; using System.Xml.Schema; namespace Microsoft.Build.Framework; internal static class ExceptionHandling { /// <summary> /// If the given exception is "ignorable under some circumstances" return false. /// Otherwise it's "really bad", and return true. /// This makes it possible to catch(Exception ex) without catching disasters. /// </summary> /// <param name="e"> The exception to check. </param> /// <returns> True if exception is critical. </returns> internal static bool IsCriticalException(Exception e) { if (e is OutOfMemoryException || e is StackOverflowException || e is ThreadAbortException || e is ThreadInterruptedException || e is AccessViolationException || e is CriticalTaskException || e is InternalErrorException) { // Ideally we would include NullReferenceException, because it should only ever be thrown by CLR (use ArgumentNullException for arguments) // but we should handle it if tasks and loggers throw it. // ExecutionEngineException has been deprecated by the CLR return true; } // Check if any critical exceptions var aggregateException = e as AggregateException; if (aggregateException != null) { // If the aggregate exception contains a critical exception it is considered a critical exception if (aggregateException.InnerExceptions.Any(innerException => IsCriticalException(innerException))) { return true; } } return false; } /// <summary> /// If the given exception is file IO related or expected return false. /// Otherwise, return true. /// </summary> /// <param name="e">The exception to check.</param> /// <returns>True if exception is not IO related or expected otherwise false.</returns> internal static bool NotExpectedException(Exception e) { return !IsIoRelatedException(e); } /// <summary> /// Determine whether the exception is file-IO related. /// </summary> /// <param name="e">The exception to check.</param> /// <returns>True if exception is IO related.</returns> internal static bool IsIoRelatedException(Exception e) { // These all derive from IOException // DirectoryNotFoundException // DriveNotFoundException // EndOfStreamException // FileLoadException // FileNotFoundException // PathTooLongException // PipeException return e is UnauthorizedAccessException || e is NotSupportedException || (e is ArgumentException && !(e is ArgumentNullException)) || e is SecurityException || e is IOException; } /// <summary> Checks if the exception is an XML one. </summary> /// <param name="e"> Exception to check. </param> /// <returns> True if exception is related to XML parsing. </returns> internal static bool IsXmlException(Exception e) { return e is XmlException #if FEATURE_SECURITY_PERMISSIONS || e is XmlSyntaxException #endif || e is XmlSchemaException || e is UriFormatException; // XmlTextReader for example uses this under the covers } /// <summary> /// If the given exception is file IO related or Xml related return false. /// Otherwise, return true. /// </summary> /// <param name="e">The exception to check.</param> internal static bool NotExpectedIoOrXmlException(Exception e) { if ( IsXmlException(e) || !NotExpectedException(e)) { return false; } return true; } /// <summary> /// If the given exception is reflection-related return false. /// Otherwise, return true. /// </summary> /// <param name="e">The exception to check.</param> internal static bool NotExpectedReflectionException(Exception e) { // We are explicitly not handling TargetInvocationException. Those are just wrappers around // exceptions thrown by the called code (such as a task or logger) which callers will typically // want to treat differently. if ( e is TypeLoadException // thrown when the common language runtime cannot find the assembly, the type within the assembly, or cannot load the type || e is MethodAccessException // thrown when a class member is not found or access to the member is not permitted || e is MissingMethodException // thrown when code in a dependent assembly attempts to access a missing method in an assembly that was modified || e is MemberAccessException // thrown when a class member is not found or access to the member is not permitted || e is BadImageFormatException // thrown when the file image of a DLL or an executable program is invalid || e is ReflectionTypeLoadException // thrown by the Module.GetTypes method if any of the classes in a module cannot be loaded || e is TargetParameterCountException // thrown when the number of parameters for an invocation does not match the number expected || e is InvalidCastException || e is AmbiguousMatchException // thrown when binding to a member results in more than one member matching the binding criteria || e is CustomAttributeFormatException // thrown if a custom attribute on a data type is formatted incorrectly || e is InvalidFilterCriteriaException // thrown in FindMembers when the filter criteria is not valid for the type of filter you are using || e is TargetException // thrown when an attempt is made to invoke a non-static method on a null object. This may occur because the caller does not // have access to the member, or because the target does not define the member, and so on. || e is MissingFieldException // thrown when code in a dependent assembly attempts to access a missing field in an assembly that was modified. || !NotExpectedException(e)) // Reflection can throw IO exceptions if the assembly cannot be opened { return false; } return true; } /// <summary> /// Serialization has been observed to throw TypeLoadException as /// well as SerializationException and IO exceptions. (Obviously /// it has to do reflection but it ought to be wrapping the exceptions.) /// </summary> internal static bool NotExpectedSerializationException(Exception e) { if ( e is SerializationException || !NotExpectedReflectionException(e)) { return false; } return true; } /// <summary> /// Returns false if this is a known exception thrown by the registry API. /// </summary> internal static bool NotExpectedRegistryException(Exception e) { if (e is SecurityException || e is UnauthorizedAccessException || e is IOException || e is ObjectDisposedException || e is ArgumentException) { return false; } return true; } /// <summary> /// Returns false if this is a known exception thrown by function evaluation /// </summary> internal static bool NotExpectedFunctionException(Exception e) { if (e is InvalidCastException || e is ArgumentNullException || e is FormatException || e is InvalidOperationException || !NotExpectedReflectionException(e)) { return false; } return true; } }