using System; using System.Diagnostics; using System.Text; using System.Reflection.Emit; using System.Reflection; using System.Runtime.Serialization; using System.Collections; #if UNITY_WINRT using SystemException = System.Exception; #endif namespace UnityEngine { #if !UNITY_WINRT public class StackTraceUtility { static string projectFolder = ""; static internal void SetProjectFolder (string folder) { projectFolder = folder; } static public string ExtractStackTrace () { StackTrace trace = new StackTrace (1, true); string traceString = ExtractFormattedStackTrace (trace).ToString (); return traceString; } static bool IsSystemStacktraceType (object name) { string casted = (string)name; return casted.StartsWith ("UnityEditor.") || casted.StartsWith ("UnityEngine.") || casted.StartsWith ("System.") || casted.StartsWith ("UnityScript.Lang.") || casted.StartsWith ("Boo.Lang.") || casted.StartsWith ("UnityEngine.SetupCoroutine"); } static public string ExtractStringFromException(System.Object exception) { string message = "", stackTrace = ""; ExtractStringFromExceptionInternal(exception, out message, out stackTrace); return message + "\n" + stackTrace; } static internal void ExtractStringFromExceptionInternal(System.Object exceptiono, out string message, out string stackTrace) { if (exceptiono == null) throw new ArgumentException("ExtractStringFromExceptionInternal called with null exception"); var exception = exceptiono as System.Exception; if (exception == null) throw new ArgumentException("ExtractStringFromExceptionInternal called with an exceptoin that was not of type System.Exception"); // StackTrace might not be available StringBuilder sb = new StringBuilder(exception.StackTrace == null ? 512 : exception.StackTrace.Length*2); message = ""; string traceString = ""; while (exception != null) { if (traceString.Length == 0) traceString = exception.StackTrace; else traceString = exception.StackTrace + "\n" + traceString; string thisMessage = exception.GetType ().Name; string exceptionMessage = ""; if (exception.Message!=null) exceptionMessage = exception.Message; if (exceptionMessage.Trim().Length != 0) { thisMessage += ": "; thisMessage += exceptionMessage; } message = thisMessage; if (exception.InnerException != null) { traceString = "Rethrow as " + thisMessage + "\n" + traceString; } exception = exception.InnerException; } sb.Append (traceString + "\n"); StackTrace trace = new StackTrace (1, true); sb.Append (ExtractFormattedStackTrace (trace)); stackTrace = sb.ToString(); } static internal string PostprocessStacktrace (string oldString, bool stripEngineInternalInformation) { if (oldString==null) return String.Empty; string [] split = oldString.Split ('\n'); StringBuilder sb = new StringBuilder(oldString.Length); for (int i=0; i ") != -1) continue; // Ignore C++ line information if (stripEngineInternalInformation && newLine.StartsWith ("[") && newLine.EndsWith("]")) continue; // Ignore starting at if (newLine.StartsWith ("at ")) { newLine = newLine.Remove (0, 3); } // Remove square brace [0x00001] int brace = newLine.IndexOf("[0x"); int braceClose = -1; if (brace != -1) braceClose = newLine.IndexOf("]", brace); if (brace != -1 && braceClose > brace) { newLine = newLine.Remove (brace, braceClose - brace + 1); } newLine = newLine.Replace(" in :0", ""); newLine = newLine.Replace(projectFolder, ""); // Unify path names to unix style newLine = newLine.Replace('\\','/'); int inStart = newLine.LastIndexOf (" in "); if (inStart != -1) { newLine = newLine.Remove(inStart, 5); newLine = newLine.Insert(inStart, " (at "); newLine = newLine.Insert(newLine.Length, ")"); } sb.Append (newLine+"\n"); } return sb.ToString (); } static internal string ExtractFormattedStackTrace (StackTrace stackTrace) { StringBuilder sb = new StringBuilder(255); int iIndex; // need to skip over "n" frames which represent the // System.Diagnostics package frames for (iIndex=0; iIndex < stackTrace.FrameCount; iIndex++) { StackFrame frame = stackTrace.GetFrame (iIndex); MethodBase mb = frame.GetMethod (); if (mb == null) continue; Type classType = mb.DeclaringType; if (classType == null) continue; // Add namespace.classname:MethodName String ns = classType.Namespace; if (ns != null && ns.Length != 0) { sb.Append (ns); sb.Append ("."); } sb.Append (classType.Name); sb.Append (":"); sb.Append (mb.Name); sb.Append ("("); // Add parameters int j=0; ParameterInfo[] pi = mb.GetParameters(); bool fFirstParam = true; while (j < pi.Length) { if (fFirstParam == false) sb.Append (", "); else fFirstParam = false; sb.Append (pi[j].ParameterType.Name); j++; } sb.Append (")"); // Add path name and line number - unless it is a Debug.Log call, then we are only interested // in the calling frame. string path = frame.GetFileName (); if (path != null && !(classType.Name == "Debug" && classType.Namespace == "UnityEngine")) { sb.Append (" (at "); if (path.StartsWith (projectFolder)) { path = path.Substring (projectFolder.Length, path.Length - projectFolder.Length); } sb.Append (path); sb.Append (":"); sb.Append (frame.GetFileLineNumber ().ToString ()); sb.Append (")"); } sb.Append ("\n"); } return sb.ToString(); } } #endif [Serializable] public class UnityException : SystemException { const int Result = unchecked ((int)0x80004003); string unityStackTrace; // Constructors public UnityException () : base ("A Unity Runtime error occurred!") { HResult = Result; } public UnityException (string message) : base (message) { HResult = Result; } public UnityException (string message, Exception innerException) : base (message, innerException) { HResult = Result; } #if !UNITY_WINRT protected UnityException (SerializationInfo info, StreamingContext context) : base (info, context) { } #endif } [Serializable] public class MissingComponentException : SystemException { const int Result = unchecked ((int)0x80004003); string unityStackTrace; // Constructors public MissingComponentException () : base ("A Unity Runtime error occurred!") { HResult = Result; } public MissingComponentException (string message) : base (message) { HResult = Result; } public MissingComponentException (string message, Exception innerException) : base (message, innerException) { HResult = Result; } #if !UNITY_WINRT protected MissingComponentException (SerializationInfo info, StreamingContext context) : base (info, context) { } #endif } [Serializable] public class UnassignedReferenceException : SystemException { const int Result = unchecked ((int)0x80004003); string unityStackTrace; // Constructors public UnassignedReferenceException () : base ("A Unity Runtime error occurred!") { HResult = Result; } public UnassignedReferenceException (string message) : base (message) { HResult = Result; } public UnassignedReferenceException (string message, Exception innerException) : base (message, innerException) { HResult = Result; } #if !UNITY_WINRT protected UnassignedReferenceException (SerializationInfo info, StreamingContext context) : base (info, context) { } #endif } [Serializable] public class MissingReferenceException : SystemException { const int Result = unchecked ((int)0x80004003); string unityStackTrace; // Constructors public MissingReferenceException () : base ("A Unity Runtime error occurred!") { HResult = Result; } public MissingReferenceException (string message) : base (message) { HResult = Result; } public MissingReferenceException (string message, Exception innerException) : base (message, innerException) { HResult = Result; } #if !UNITY_WINRT protected MissingReferenceException (SerializationInfo info, StreamingContext context) : base (info, context) { } #endif } }