Can I change the current stack in C #?

In short, I need to change the current stack trace to C #, so that the method I call (which I cannot change) will think that someone else called it.

Now, to give a little context on why I need to do such a terrible hack.

Unity3d Debug.Log creates a new entry in the developer console. When you double-click on it, it will open the IDE to display the exact file and line that were responsible for this entry. However, for various reasons (disabling debugging in production, making it suitable for use in other threads), I created the Print wrapper class, which I use instead of UnityEngine.Debug.

But with the wrapper, now that the developer clicks on the log entry in the console, Print opens, not the actual place where Print.Log was called. And since Debug.Log does this regardless of the error message or context object, I decided that it uses the call stack to identify the open file. Needless to say, I want to fix it.

+7
c # mono unity3d
source share
2 answers

I do not believe that this is possible. Considering the source code for Environment.StackTrace and the subsequent GetStackTrace() call, we can see it creates a stack trace every time it is called. Since there is nothing that could be done to change part of its work, I think it is safe to conclude that you cannot change the stacktrace without changing what it is called.

If you have the opportunity to do this, you can use something like this, which boils down to fetching the current stacktrace and using reflection to modify the very latest StackFrame method to mimic what you need.

 void Main() { DoSomething(); } void DoSomething(){ Console.WriteLine (Environment.StackTrace); // Last frame: at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo) var frames = new StackTrace().GetFrames(); var lastframe = frames[0]; // last frame: DoSomething at offset 100 in file:line:column <filename unknown>:0:0 var methodField = lastframe.GetType().GetField("method", BindingFlags.Instance | BindingFlags.NonPublic); var redirectedMethod = typeof(Redirect).GetMethod("RedirectToMethod", BindingFlags.Instance | BindingFlags.Public); methodField.SetValue(lastframe, redirectedMethod); Console.WriteLine (frames); // last frame: RedirectToMethod at offset 100 in file:line:column <filename unknown>:0:0 Console.WriteLine (Environment.StackTrace); // last frame: at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo) } public class Redirect { public void RedirectToMethod() { } } 

But again: this is very fragile and not applicable in your current situation. What you are trying to do is quite exotic and should probably be avoided altogether.

As for the real solution: I'm afraid that I have no experience with Unity, so I can only google, but this stream might be interesting for you. I mentioned .NET sources here, but you can find very similar code in the Mono source.

+3
source share

Work with this, compile your Print class into a single compatible Dll (.Net 2, I think). When you double-click on the log, the console will ignore the DLL information and go to where the print was called.

+1
source share

All Articles