引起FileNotFoundException原因通用分析过程
有的时候,你在双击一个托管程序,或者使用Assembly.Load方法加载一些Assembly的时候,CLR会抛出System.FileNotFoundException,这种异常经常让人误解。例如有一个托管程序A,引用了dll B,虽然A和B都在同一个文件夹里面,但是当你试图运行A的时候,还是会有类似下面的异常抛出来:
Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly \'TestLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=eb9fb5aa4f452bda\' or one of its dependencies. The located assembly\'s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: \'TestLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=eb9fb5aa4f452bda\' at App.Main() |
在工作当中,我发现很多程序员在资源管理器里面双击程序以后,看到程序在启动阶段抛出异常就束手无措了,因为这种异常不像程序在执行过程中发生的异常 — 还有机会调试,这种异常不能通过单步跟踪的方式来发现问题所在。
像这种托管程序在资源管理器通过双击启动时就抛出异常的情况,我建议大家在排错的时候,首先在命令行程序里面重新执行一下出错的程序,当然啦,结果是一样的 — 还是启动不起来,但是在命令行里面执行有一个好处,CLR会将完整的异常信息打印在命令行里面,很多异常信息实际上都提供了丰富的错误原因描述,有的时候还提供了排错需要使用的方法,例如下图:
按照上面红线高亮显示的部分设置好注册表对应的键值,并且重新执行一遍程序你就可以找出错误原因了。
除了上面说到的方法,CLR实际上还提供了一个叫做FUSLOGVW.exe的工具,也是可以用来检查FileNotFoundException的原因的,用法如下:
1. 打开FUSLOGVW.exe,点击“Settings…”按钮。
2. 在弹出的对话框里面选中“Log bind failures to disk”(告诉CLR将加载Assembly失败的一些错误信息保存在磁盘里)。
3. 为了能够看到错误信息,勾上“Enable custom log path”复选框,并且在“Custom log path”文本框里面设置好保存的路径(注意,只能填写文件夹的完整路径)
4. 重新执行发生错误的程序,发生FileNotFoundException异常以后,切换回FUSLOGVW.exe并点击“Refresh”按钮。
5. 这时候你应该可以在旁边的列表框里面看到有一些新列表项(都是加载失败的Assembly的具体错误信息),双击其中一项就可以看到加载失败的具体原因了。