【问题标题】:Can I change current stacktrace in C#?我可以在 C# 中更改当前堆栈跟踪吗?
【发布时间】:2014-08-11 13:22:38
【问题描述】:

简而言之,我需要在 C# 中修改当前堆栈跟踪,以便我调用的方法(我无法修改)会认为是其他人调用它。

现在,让我们稍微介绍一下为什么我需要进行如此可怕的黑客攻击。

在 Unity3d 中,Debug.Log 在开发者控制台中创建一条新记录。当您双击它时,它会打开 IDE 以显示负责该记录的确切文件和行。但是,由于各种原因(在生产中禁用调试,使其在其他线程中可用),我创建了一个包装类 Print,而不是 UnityEngine.Debug。

但是使用 wrapper,现在当开发人员点击控制台中的日志记录时,打开的是 Print,而不是调用 Print.Log 的实际位置。而且由于Debug.Log 不考虑错误消息或上下文对象,我认为它使用调用堆栈来识别要打开的文件。不用说,我想解决这个问题。

【问题讨论】:

  • 我理解你这样做的动机。我认为这是不可能的,因为它可以规避任何代码访问安全概念
  • 我也这么认为,但我必须问清楚。
  • answers.unity3d.com/questions/176422/debug-wrapper-class.html 找到此链接,建议将您的调试类移至不同的程序集。
  • @SirBraneDamuj 我可以确认该建议有效,这就是我的记录器的工作方式。

标签: c# mono unity3d


【解决方案1】:

我不相信这是可能的。查看Environment.StackTrace 的源代码和随后的GetStackTrace() 调用,我们可以在每次调用它时看到它creates the stacktrace。由于似乎没有任何东西可以注入来改变它的某些工作,我认为可以安全地得出结论,如果不修改堆栈跟踪的调用方式,就无法更改它。

如果您有可能这样做,您可以使用类似这样的方法来检索当前堆栈跟踪并使用反射来更改最新的StackFrame 的method 字段以模仿您的身份'在之后。

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() { }
}

但再次重申:这非常脆弱,不适用于您当前的情况。您正在尝试做的事情相当奇特,应该完全避免。

至于实际的解决方案:恐怕我对 Unity 没有任何经验,所以我只能用谷歌搜索,但 this thread 可能对你很感兴趣。我在这里提到了 .NET 源代码,但您可以在 Mono 源代码中找到 very similar code。

【讨论】:

    【解决方案2】:

    解决此问题的方法是将您的 Print 类编译为统一兼容的 Dll(我认为是 .Net 2)。双击日志时,控制台将忽略 dll 信息并转到调用 Print 的位置。

    【讨论】:

      猜你喜欢
      • 2010-09-17
      • 1970-01-01
      • 2017-08-31
      • 2012-06-27
      • 2019-11-05
      • 2010-11-07
      • 2012-10-29
      相关资源
      最近更新 更多