.net &引用;无法加载文件或程序集“;仅在调试时在catch块中结束

.net &引用;无法加载文件或程序集“;仅在调试时在catch块中结束,.net,exception-handling,fusion,.net,Exception Handling,Fusion,我运行了一个在服务器上开发的windows服务,该服务器缺少一个预先需要的软件组件 果然,服务崩溃了,出现了System.IO.filenotfoundexpetion:无法加载文件或程序集… 问题是,当我在调试中部署完全相同的服务时,围绕失败代码的catch块实际上被命中,我有机会做出反应(记录、重试) 例如: private void SampleMethodInService() { try { // this method uses objects tha

我运行了一个在服务器上开发的windows服务,该服务器缺少一个预先需要的软件组件

果然,服务崩溃了,出现了
System.IO.filenotfoundexpetion:无法加载文件或程序集…

问题是,当我在调试中部署完全相同的服务时,围绕失败代码的catch块实际上被命中,我有机会做出反应(记录、重试)

例如:

private void SampleMethodInService()
{
    try
    {
        // this method uses objects that reside in an assembly that`s missing
        MethodInMissingAssembly();
    }
    catch(Exception e)
    {
         // i'd like to log what happened, but don't get the chance.
    }
}
如果上面的代码是在debug中编译的,catch块将处理异常。 如果上面的代码是在发行版中编译的,则不会命中catch块,进程将失败

我的问题是:为什么会这样


我在谷歌上搜索了很长时间,但没有找到任何线索。

这取决于许多因素

第一种明显的可能性是,当您将代码作为服务加载时,它使用的是之前缺少的依赖项,而不是捕获异常的方法。应用程序第一次尝试加载时将崩溃

如果您确定此方法是第一个使用此依赖项的方法,则仍有可能在应用程序启动时加载依赖项。某些运行时环境会这样做(例如asp.net),在这种情况下,捕获调用程序集的方法将是毫无意义的。如果您在调试(或单元测试)中运行相同的东西,您可能会得到与IIS不同的行为(我知道您在这里不使用IIS,但我只是给出一个示例)

更多信息

一种可能的解决方案是在应用程序的入口点(App_Start、Main()等)通过反射加载所有引用的程序集,并在那里捕获。有关更多信息,请参阅


关于为什么可能缺少程序集,可能还有其他一些解决方案。我猜它实际上并没有与您的应用程序一起部署。你希望它出现在GAC里吗?是否有一种方法可以检查是否使用注册表安装了第三方依赖项?如果是这种情况,您可能会引发信息更丰富的错误。

Scattered
catch
块不是记录异常的正确方法。如果您为未处理的异常添加了一个全局处理程序,并将日志代码放在那里,您就会看到跟踪。@CodyGray这样做的问题是我无法继续服务正在做的事情。所以一般来说,我不确定你说的话是否正确。也许你可以尝试在你的exe()上使用Sysinternal的procmon。您应该看到进程何时尝试查找程序集。如果将其与一些日志记录混合使用,则可以检查在调试和运行中是否以相同的顺序发生release@EvrenKuzucuoglu由于代码位于try块中,优化器不会从中删除代码。这将极大地改变语义,我们所有人的赌注都没有了。我不认为它会被优化掉,但可能在发布版中,应用程序实际上会在调用该方法之前尝试加载程序集。我只是建议将procmon作为一种验证二进制文件的调试和发布版本何时尝试打开该依赖关系的方法。使用它,您可以看到CLR试图获取程序集的调用的时间线和结果。我使用调试中使用的完全相同的代码运行服务-异常已处理,使用发布中使用的完全相同的代码运行服务-未处理异常。这两种情况都作为服务运行。由于前面的注释,第一点和第二点不相关。我不是在寻找一种预先检测这种情况的方法,而是要理解为什么编译模式会以这种方式改变行为。好吧,那不是正确的答案。只是想确定一下,您的代码中是否有在调试中运行不同的东西,比如#ifdef debug?我想不出一个版本优化会造成这种情况。谢谢Evren,我也没有任何预编译条件