using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; namespace Volian.Base.Library { // This provides a more robust stack trace than what visual studio offers public static class vlnStackTrace { public static string GetStack(string str, params object[] objects) { return string.Format(str, objects) + StackToString(); } public static void ShowStack(string str, params object[] objects) { Console.WriteLine(string.Format(str, objects) + StackToString()); } public static string GetStack() { return StackToString(); } public static string GetStack(bool showSame) { return StackToString(showSame); } public static void ShowStack() { Console.WriteLine(StackToString()); } private static string StackToString() { return StackToString(true); } private static string StackToString(bool showSame) { StringBuilder sb = new StringBuilder(); StackTrace st = new StackTrace(true); StackFrame[] sfs = st.GetFrames(); int ii = 0; string sLast = ""; string sThis = ""; int imax = MatchingStackFrame(sfs); foreach (StackFrame sf in sfs) { if (showSame && imax == 0) sb.Append(string.Format("\r\n{0}---------", "".PadLeft(ii++ * 2))); imax--; if (ii < 2) ii++; else { string sMethod = sf.GetMethod().Name; string sNamespace = sf.GetMethod().ReflectedType.Namespace; string sType = sf.GetMethod().ReflectedType.Name; if (sf.GetFileLineNumber() != 0) { sMethod += string.Format(" {0}[{1}]", sf.GetFileName(), sf.GetFileLineNumber()); sThis = ""; } else { sThis = sNamespace; } if (sLast == sThis && sThis != "") sb.Append(string.Format("\t*.{0}.{1}", sType, sMethod)); else sb.Append(string.Format("\r\n{0}{1}.{2}.{3}", "".PadLeft(ii++ * 2), sNamespace, sType, sMethod)); } sLast = sThis; } return sb.ToString(); } public static void ShowStackLocal(string str, params object[] objects) { Console.WriteLine(string.Format(str, objects) + StackToStringLocal(2,10)); } public static void ShowStackFirstLocal(string str) { Console.WriteLine(str + "\r\n" + StackToStringLocal(3, 0)); } public static void ShowStackLocal(string str,int start) { Console.WriteLine(str + "\r\n" + StackToStringLocal(start,1)); } public static void ShowStackLocal(int start, int limit, string str, params object[] objects) { Console.WriteLine(string.Format(str, objects) + StackToStringLocal(start, limit)); } public static string StackToStringLocal(int start, int limit) { StringBuilder sb = new StringBuilder(); string sep = "\r\n"; StackTrace st = new StackTrace(true); StackFrame[] sfs = st.GetFrames(); int count = 0; int localCount = 0; foreach (StackFrame sf in sfs) { count++; if (count > start) { if (sf.GetFileLineNumber() != 0) { string sMethod = sf.GetMethod().Name; string sNamespace = sf.GetMethod().ReflectedType.Namespace; string sType = sf.GetMethod().ReflectedType.Name; sMethod += string.Format(" {0}[{1}]", sf.GetFileName(), sf.GetFileLineNumber()); sb.Append(sep + string.Format("{0}.{1}.{2}", sNamespace, sType, sMethod)); localCount ++; if (localCount >= limit) return sb.ToString(); sep = "\r\n" + "".PadRight(localCount *2); } } } if (localCount > 0) return sb.ToString(); return "No Local Method"; } public static string CalledFrom { get { StackTrace st = new StackTrace(true); StackFrame[] sfs = st.GetFrames(); int count = 0; foreach (StackFrame sf in sfs) { if (sf.GetFileLineNumber() != 0) // Only look at Local Methods { count++; if (count > 4) // The fourth entry should be the Calling Method { string sType = sf.GetMethod().ReflectedType.Name; string sMethod = sf.GetMethod().Name; return string.Format("{0}.{1}[{2}]", sType, sMethod, sf.GetFileLineNumber()); } } } return "No Local Method"; } } public static string CalledFromCSLA { get { StackTrace st = new StackTrace(true); StackFrame[] sfs = st.GetFrames(); int count = 0; string lastWasCSLA = null; foreach (StackFrame sf in sfs) { string sType = sf.GetMethod().ReflectedType.FullName; string sMethod = sf.GetMethod().Name; if (sType.StartsWith("VEPROMS.CSLA.Library") && !sType.StartsWith("VEPROMS.CSLA.Library.Database") && !sMethod.StartsWith("DataPortal") && !sMethod.StartsWith("SetParentSectionAndDocVersion"))// Only look at Local Methods lastWasCSLA = string.Format("{0}.{1}[{2}]", sType, sMethod, sf.GetFileLineNumber()); else if (lastWasCSLA != null) return lastWasCSLA; } return "No CSLA Method"; } } private static StackFrame[] _LastSFS; private static int MatchingStackFrame(StackFrame[] sfs) { int iFound = -1; if (_LastSFS != null) { // start at the far end and work backward for (int i = 1; iFound < 0 && i <= sfs.Length && i <= _LastSFS.Length; i++) { if (!Match(sfs[sfs.Length - i],_LastSFS[_LastSFS.Length - i])) iFound = 1+ sfs.Length - i; } } if (iFound < 0) iFound = sfs.Length; _LastSFS = (StackFrame[])sfs.Clone(); return iFound; } private static bool Match(StackFrame stackFrame1, StackFrame stackFrame2) { if (stackFrame1.GetMethod().Name != stackFrame2.GetMethod().Name) return false; if (stackFrame1.GetMethod().DeclaringType.FullName != stackFrame2.GetMethod().DeclaringType.FullName) return false; if (stackFrame1.GetILOffset() != stackFrame2.GetILOffset()) return false; return true; } public static bool ScrollInStack() { StackTrace st = new StackTrace(true); StackFrame[] sfs = st.GetFrames(); bool retval = false; foreach (StackFrame sf in sfs) { string sMethod = sf.GetMethod().Name; string sNamespace = sf.GetMethod().ReflectedType.Namespace; string sType = sf.GetMethod().ReflectedType.Name; if (sMethod.ToUpper().Contains("SCROLL") || sType.ToUpper().Contains("SCROLL")) { retval = true; Console.WriteLine("{0}.{1}.{2}", sNamespace, sType, sMethod); } } return retval; } /// /// This will clear the Output window when run in the Development Environment /// Add EnvDTE and EnvDTE80 to references from .NET /// public static void ClearOutputWindow() { #if (DEBUG) try { EnvDTE80.DTE2 dte2 = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.8.0"); dte2.ToolWindows.OutputWindow.ActivePane.Clear(); } catch (Exception ex) { Console.WriteLine("ClearOutputWindow {0} - {1}\r\n{2}", ex.GetType().Name, ex.Message, ex.StackTrace); } #endif } } }