代码之家  ›  专栏  ›  技术社区  ›  Marek

为什么不可能捕获MissingMethodException?

  •  11
  • Marek  · 技术社区  · 14 年前

    ApplicationDeployment.CurrentDeployment.CheckForDetailedUpdate(false) 方法仅适用于SP2)。

    我想检查SP2是否在应用程序启动期间存在。我试图通过在调用仅SP2方法后捕获MissingMethodException来检测这一点。

        /// <summary>
        /// The SP2 bootstrapper does not allow HomeSite installation
        /// http://msdn.microsoft.com/en-us/vstudio/bb898654.aspx
        /// So we only advice the user to download .NET 2.0 SP2 manually.
        /// </summary>
        private void CheckDotNet2SP()
        {
            WaitHandle wh = new AutoResetEvent(true);
            try
            {
                wh.WaitOne(1); //this method is .NET 2.0 SP2 only
            }
            //NOTE: this catch does not catch the MissingMethodException
            catch (Exception) //change to catch(MissingMethodException) does not help
            {
                //report that .NET 2.0 SP2 is missing
            }
            finally
            {
                wh.Close();
            }
        }
    

    AppDomain.CurrentDomain.UnhandledException 事件处理程序。

    MissingMethodException怎么可能没有被捕获?我可以想象这是一个特例——CLR命中了一个不存在的方法,并且不可能以某种方式将其传递给catch块。我想了解这背后的原理。

    4 回复  |  直到 14 年前
        1
  •  15
  •   Jon Skeet    14 年前

    我怀疑这是在JIT时间发生的,在方法被正确输入之前,也就是说,在你的catch块被命中之前。它是 如果你抓住 MissingMethodException 打电话 CheckDotNet2SP 具有 MethodImpl[MethodImplOptions.NoInlining]

    您可以通过反射检查方法的存在,而不是尝试调用它。

        2
  •  12
  •   Abel    14 年前

    有一些例外被定义为“不可恢复”。其中之一就是 MissingMethodException ,因为如果类中缺少方法,这是一个严重错误,需要卸载类并重新加载一个新类才能恢复,而这不能简单地完成(如果有的话)。

    如果您只想知道是否安装了SP2,那么默认方法是使用引导应用程序,该应用程序只检查已安装的版本。如果一切正常,它会运行应用程序,如果没有,它会显示一条很好的消息。


    OP要求的更新:
    OutOfMemoryException (同步时可以捕获), StackOverflowException (永远不会被抓住), ThreadAbortException (可以捕获,但很特殊,因为它将在捕获块的末尾自动重新提升), BadImageFormatException MissingManifestResourceException 如果您试图在抛出异常的程序集中捕获它(如果您动态加载它,与 ,你有能力抓住它)。一般来说,任何不从 Exception 很难捕捉(但可以使用通用的try/catch块捕捉它们)。

    还有其他的,但是上面的前三个是你在实践中最常遇到的。

        3
  •  4
  •   desco    14 年前

    在JIT编译步骤中引发了异常,所以您没有单步执行方法。 尝试此版本:

        private bool CheckDotNet2SP()
        {
            try
            {
                CheckImpl();
                return true;
            }
            catch (MissingMethodException)
            {
                return false;
            }
        }
    
        [MethodImpl(MethodImplOptions.NoInlining)]
        private void CheckImpl()
        {
            using (var wh = new ManualResetEvent(true))
                wh.WaitOne(1);
        }
    
        4
  •  3
  •   Dirk Vollmar    14 年前

    您可以使用反射来查看该方法是否存在。

    private void CheckDotNet2SP()
    {
        return typeof(WaitHandle).GetMethod("WaitOne", new Type[] { typeof(int) }) 
           != null;
    }