我可以在C#中更改当前堆栈跟踪吗?
简而言之,我需要修改C#中的当前堆栈跟踪,这样我调用的方法(我无法修改)会认为是其他人调用了它 现在,给一个小的背景,为什么我需要做这样一个可怕的黑客 在Unity3d中,在开发人员控制台中创建新记录。当您双击它时,它会打开IDE以显示负责该记录的确切文件和行。然而,由于各种原因(在生产中禁用调试,使其在其他线程中可用),我创建了一个包装类我可以在C#中更改当前堆栈跟踪吗?,c#,mono,unity3d,C#,Mono,Unity3d,简而言之,我需要修改C#中的当前堆栈跟踪,这样我调用的方法(我无法修改)会认为是其他人调用了它 现在,给一个小的背景,为什么我需要做这样一个可怕的黑客 在Unity3d中,在开发人员控制台中创建新记录。当您双击它时,它会打开IDE以显示负责该记录的确切文件和行。然而,由于各种原因(在生产中禁用调试,使其在其他线程中可用),我创建了一个包装类Print,我使用它代替UnityEngine.debug 但是使用wrapper,现在当开发人员在控制台中单击日志记录时,打开的是Print,而不是调用Pr
Print
,我使用它代替UnityEngine.debug
但是使用wrapper,现在当开发人员在控制台中单击日志记录时,打开的是
Print
,而不是调用Print.log
的实际位置。由于无论错误消息或上下文对象如何,Debug.Log
都会执行此操作,因此我认为它使用调用堆栈来标识要打开的文件。不用说,我想解决这个问题。我认为这是不可能的。查看的源代码和后续调用,我们可以在每次调用时看到它。由于似乎没有任何东西可以注入来改变它的某些工作方式,因此我认为可以得出这样的结论:如果不修改stacktrace的调用方式,就无法更改它
如果您有可能这样做,您可以使用类似这样的方法来检索当前stacktrace,并使用反射来更改最近的方法
字段,以模拟您所追求的内容
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() { }
}
void Main()
{
DoSomething();
}
无效剂量测定法(){
Console.WriteLine(Environment.StackTrace);//最后一帧:在System.Environment.GetStackTrace(异常e,布尔needFileInfo)
var frames=new StackTrace().GetFrames();
var lastframe=frames[0];//最后一帧:文件:行:列:0:0中偏移量为100的DoSomething
var methodField=lastframe.GetType().GetField(“方法”,BindingFlags.Instance | BindingFlags.NonPublic);
var redirectedMethod=typeof(Redirect).GetMethod(“RedirectToMethod”,BindingFlags.Instance | BindingFlags.Public);
设置值(lastframe,redirectedMethod);
Console.WriteLine(frames);//文件:行:列:0:0中偏移量为100的最后一帧:重定向到方法
Console.WriteLine(Environment.StackTrace);//最后一帧:在System.Environment.GetStackTrace(异常e,布尔needFileInfo)
}
公共类重定向{
public void RedirectToMethod(){}
}
但再一次:这是非常脆弱的,不适用于你目前的情况。你正在尝试做的事情是相当奇特的,应该完全避免
至于一个实际的解决方案:恐怕我对Unity没有任何经验,所以我只能用谷歌搜索,但你可能会感兴趣。我在这里提到了.NET源代码,但您可以在Mono源代码中找到。解决方法是将您的Print类编译成与unity兼容的Dll(.NET 2)。双击日志时,控制台将忽略dll信息并转到调用Print的位置 我理解你这么做的动机。我认为这是不可能的,因为这将使规避任何代码访问安全概念成为可能,我也这么认为,但我必须要求确保。找到此链接,建议将调试类移动到其他程序集。@SirBraneDamuj我可以确认此建议有效,我的记录器就是这样工作的。