【问题标题】:Trace all handled exception跟踪所有处理的异常
【发布时间】:2015-11-21 02:30:03
【问题描述】:

我试图了解为什么一个部署的应用程序不能正常工作。我已将问题归结为特定的更新例程。可悲的是,该例程被嵌入到什么都不做的 try-catch 中。

bool requireUpdate = false;
try
{
    requireUpdate = !client.IsUpToDate();
}
catch{ }

我需要一种方法来获取异常无需重新编译并进行部署。

有没有办法修改app.config 文件,以便它可以将所有已处理的异常追踪到日志文件,无论它们是如何处理的?

【问题讨论】:

  • 负责编写此代码的人是必须接受审判的罪犯:-)
  • 我知道,而且我也为在编码时授权此类代码而感到难过。

标签: c# exception-handling


【解决方案1】:

仅仅因为我今天发现了这一点(我真的很喜欢用不太有用的答案来复活旧问题!),因为 .NET4,AppDomain 上有一个新事件,它在任何异常处理之前触发。

在您的应用设置代码中的某个位置(例如Program.MainApplication_OnStart 等),您可以添加一个处理程序:

class Program
{
    static void Main(string[] args)
    {
        AppDomain.CurrentDomain.FirstChanceException 
            += FirstChanceException

        // ...rest of your app startup
    }

    private static bool LogFirstChanceExceptions
    {
        get  
        {
            return ConfigurationManager.AppSettings["logFirstChanceExceptions"] 
                                       .Equals(bool.TrueString)
        }
    }

    private static void FirstChanceException(object sender,
                                             FirstChanceExceptionEventArgs e)
    {
        if (e != null && 
            e.Exception != null &&
            LogFirstChanceExceptions)
        {
            Console.Error.WriteLine("First-chance {0}: {1}",
                                    e.Exception.GetType(), 
                                    e.Exception.Message);
        }
    }
}

(未经测试,无保修等。未图示:任何重入处理,以防FirstChanceException 处理程序本身抛出异常)

对 OP 没有帮助,但它可能会帮助那些可以重新编译的人,包括一些允许他们在未来切换这种跟踪的东西。

【讨论】:

    【解决方案2】:

    不幸的是,对于 已处理 异常,我们无能为力,因为它们 已被处理(即使非常糟糕,就像您的情况一样)。

    获得它们的最佳方法是重写/重新编译/部署。

    【讨论】:

    • +1 用于重写代码。今天是这个功能,明天是另一个。修复坏代码,这是唯一的解决方案。
    • @Aliostad - 您显然以前从未使用过分析器。有可能在每次分析会话之前/之后必须停止应用程序,并且很可能无论如何它都不是生产环境的选项(安装分析器并运行它可能会对系统产生不利影响)。
    【解决方案3】:

    更新

    CLR 分析可以帮助你!

    看看这个链接: http://msdn.microsoft.com/en-us/magazine/cc301839.aspx

    您基本上可以跟踪您的异常情况:

    “分析 API 提供了一组广泛的回调,详细描述了异常处理周期的搜索、展开和最终阶段。一个有趣的分析场景将监视托管异常并提供附加信息,例如抛出的 Win32 线程异常、位于堆栈顶部的函数、该函数的参数以及发生异常时范围内的局部变量。”

    【讨论】:

    • 它没有崩溃;它什么都不做。
    • 你在说什么崩溃?它正在吞咽,这比崩溃更糟糕:-)
    • 是的,使用分析器 API 绝对是一种方法,但我认为你会浪费在它上面的时间最好用来重写这段代码。此外,使用 CLR API 需要一些管理权限,并且在使用完毕后可能会导致应用程序崩溃,这在生产环境中不是一个好主意。
    【解决方案4】:

    使用低级调试器,例如 WinDbg,您将能够知道第一次机会异常。

    【讨论】:

      【解决方案5】:

      我在 Java 中使用过的技巧:

      遍历应用程序中的所有 catch 块,寻找空的。将调试或跟踪消息添加到块中,说明“捕获预期异常”和异常。无论如何,您都应该这样做,并制定一个绝对不能接受默默吞下异常的策略。

      如果未能清除异常,则重新编译基本异常,如果应用程序处于调试(或跟踪)模式,则向无参数构造函数添加一个块以记录堆栈跟踪。显然,如果您的应用程序/库有自己的异常层次结构,这更容易做到,但有办法注入这种行为(这里在 C# 中执行此操作的方式与我完成此操作的方式不同)

      【讨论】:

      • 他想要一个不需要重新编译的解决方案。
      【解决方案6】:

      还有另一种选择,但它可能漂亮也可能不漂亮:痣。

      技术上用于单元测试,Moles 允许您用委托替换任何 .NET 方法。您也许可以使用它来用您的委托替换该方法,而不是做您想做的事情。

      您也许可以将原始方法替换为调用 client.IsUpToDate() 的委托,这样您就可以阻止异常?

      痣是 Pex 的一部分: http://research.microsoft.com/en-us/projects/pex/default.aspx

      【讨论】:

        【解决方案7】:

        这个solution 可能就是您要找的。
        基本上指令是使用这个代码块:

        System.Diagnostics.EventLog.WriteEntry("MyEventSource", exception.StackTrace,
        System.Diagnostics.EventLogEntryType.Warning);

        此外,来自同一链接的 app.config 似乎是这样的: <system.diagnostics> <switches>

            <add name="MySwitch" value="Verbose" />
        </switches>
        <trace autoflush="true">
            <listeners>
                <add name="EventLogger"
                     type="System.Diagnostics.EventLogTraceListener"
                     initializeData="NameOfYourApplication" />
            </listeners>
        </trace>
        

        【讨论】:

        • 错误仍然以某种方式弄乱我的语法
        • 这显示了如何使用跟踪,但我看不出这在这种情况下有什么帮助。
        • 无需重新编译... jeebus 的甜蜜妈妈
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-25
        • 2017-05-08
        • 2012-09-21
        • 2021-06-16
        • 2023-03-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多