再谈System.BadImageFormatException
今天,当我们继续学习.NET异常处理系列时,我们将查看System.BadImageFormatException。System.BadImageFormatException与GIF或JPG无关,而是在.NET应用程序尝试加载与当前公共语言运行库(CLR)所需的正确格式不匹配的动态链接库(.dll)或可执行文件(.exe)时发生。
在本文中,我们将看到System.BadImageFormatException在.NET异常层次结构中的确切位置,并查看System.BadImageFormatException的一些潜在原因,让我们开始讨论它!
如前所述,System.BadImageFormatException发生在非常特殊的情况下:当.NET试图使用.dll或.exe时,即以某种方式与当前公共语言运行库不兼容。“不兼容的公共语言运行时”的定义可能有所不同,但通常这意味着.NET版本(1.1、2.0等)或各种编译程序集的CPU类型(32位与64位)不匹配。
最后,System.BadImageFormatExceptions表示版本控制不兼容。对于许多现代软件应用程序,的主要版本通常包括打破兼容性问题,防止与以前版本的某些方面向后兼容。.NET程序集(.dll或.exe)基本相同,尝试使用包含不兼容项的两种不同类型的程序集通常会生成System.BadImageFormatException。
为了说明这一点,我们将通过几个不同的例子。我已经包含了下面的完整代码示例以供参考,之后我们将更详细地探讨细节:
using System;
using System.Reflection;
using Utility; namespace Airbrake.BadImageFormatException
{
class Program
{
static void Main(string[] args)
{
LoadingNonDotNetLibraryExample();
Logging.Log("-----------------");
DifferingCPUExample();
Logging.Log("-----------------");
OldDotNetExample();
} private static void LoadingNonDotNetLibraryExample()
{
try
{
// Generate path to notepad.exe.
string filePath = Environment.ExpandEnvironmentVariables("%windir%") + @"\System32\notepad.exe";
Assembly assem = Assembly.LoadFile(filePath);
}
catch (System.BadImageFormatException exception)
{
Logging.Log(exception);
}
} private static void DifferingCPUExample()
{
try
{
// Load Utility.dll, a 64-bit assembly.
Assembly assem = Assembly.LoadFrom(@".\Utility.dll");
Logging.Log(assem.ToString());
}
catch (System.BadImageFormatException exception)
{
Logging.Log(exception);
}
} private static void OldDotNetExample()
{
try
{
// Load Author-1.1.dll (compiled in .NET 1.1).
Assembly assem = Assembly.LoadFrom(@".\Author-1.1.dll");
Logging.Log(assem.ToString());
}
catch (System.BadImageFormatException exception)
{
Logging.Log(exception);
}
}
}
} using System;
using System.Diagnostics; namespace Utility
{
/// <summary>
/// Houses all logging methods for various debug outputs.
/// </summary>
public static class Logging
{
/// <summary>
/// Outputs to <see cref="System.Diagnostics.Debug.WriteLine"/> if DEBUG mode is enabled,
/// otherwise uses standard <see cref="Console.WriteLine"/>.
/// </summary>
/// <param name="value">Value to be output to log.</param>
public static void Log(object value)
{
#if DEBUG
Debug.WriteLine(value);
#else
Console.WriteLine(value);
#endif
} /// <summary>
/// When <see cref="Exception"/> parameter is passed, modifies the output to indicate
/// if <see cref="Exception"/> was expected, based on passed in `expected` parameter.
/// <para>Outputs the full <see cref="Exception"/> type and message.</para>
/// </summary>
/// <param name="exception">The <see cref="Exception"/> to output.</param>
/// <param name="expected">Boolean indicating if <see cref="Exception"/> was expected.</param>
public static void Log(Exception exception, bool expected = true)
{
string value = $"[{(expected ? "EXPECTED" : "UNEXPECTED")}] {exception.ToString()}: {exception.Message}";
#if DEBUG
Debug.WriteLine(value);
#else
Console.WriteLine(value);
#endif
}
}
}
引发System.BadImageFormatException的第一种(也可以说是最常见的)方法是尝试使用非托管程序集时,就像它是使用.NET框架创建的程序集一样。非托管程序集是由.NET的公共语言运行库未处理和编译的代码生成的程序集。这包括许多较旧的应用程序和程序集,特别是为32位系统创建的应用程序和程序集。
作为一个例子,这里我们试图加载一个非托管程序集—特别是位于Windows/System32目录中的众所周知的notepad.exe程序集:
private static void LoadingNonDotNetLibraryExample()
{
try
{
// Generate path to notepad.exe.
string filePath = Environment.ExpandEnvironmentVariables("%windir%") + @"\System32\notepad.exe";
Assembly assem = Assembly.LoadFile(filePath);
}
catch (System.BadImageFormatException exception)
{
Logging.Log(exception);
}
}
.NET对此不满意,因为notepad.exe不受管理(不是使用.NET编译的),因此引发System.BadImageFormatException:
[EXPECTED] System.BadImageFormatException: The module was expected to contain an assembly manifest. (Exception from HRESULT: 0x80131018)
at System.Reflection.RuntimeAssembly.nLoadFile(String path, Evidence evidence)
at System.Reflection.Assembly.LoadFile(String path)
at Airbrake.BadImageFormatException.Program.LoadingNonDotNetLibraryExample() in D:\work\Airbrake.io\Exceptions\.NET\Airbrake.BadImageFormatException\Program.cs:line : The module was expected to contain an assembly manifest. (Exception from HRESULT: 0x80131018)
另一种可能引发System.BadImageFormatException的方法是尝试加载使用不同于当前在.NET上执行的CPU类型编译的程序集。
例如,在我们的许多代码片段中,我们一直在使用包含日志类的简单实用程序名称空间,这使得在调试和测试期间输出日志信息更加容易。默认情况下,Utility.dll编译为64位程序集。但是,如果我们将当前的CPU配置切换为以x86(32位)CPU执行,则会遇到一些问题:
private static void DifferingCPUExample()
{
try
{
// Generate path to Utility.dll, a 64-bit assembly.
Assembly assem = Assembly.LoadFrom(@".\Utility.dll");
Logging.Log(assem.ToString());
}
catch (System.BadImageFormatException exception)
{
Logging.Log(exception);
}
}
当试图加载Utility.dll程序集(64位)时,当将当前代码编译为32位时,.NET抛出System.BadImageFormatException,通知我们这些格式不匹配:
[EXPECTED] System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
at System.Reflection.RuntimeAssembly.nLoadFile(String path, Evidence evidence)
at System.Reflection.Assembly.LoadFile(String path)
at Airbrake.BadImageFormatException.Program.DifferingCPUExample() in D:\work\Airbrake.io\Exceptions\.NET\Airbrake.BadImageFormatException\Program.cs:line : An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
最后,如果尝试加载使用更旧版本的.NET(如.NET 1.1)编译的程序集,我们也会遇到问题:
private static void OldDotNetExample()
{
try
{
// Load Author-1.1.dll (compiled in .NET 1.1).
Assembly assem = Assembly.LoadFrom(@".\Author-1.1.dll");
Logging.Log(assem.ToString());
}
catch (System.BadImageFormatException exception)
{
Logging.Log(exception);
}
}
在上述情况下,System.BadImageFormatException通常会在编译时抛出,而不是在运行时抛出,因为.NET编译器在试图首先执行任何代码之前都会识别出不兼容。
再谈System.BadImageFormatException的更多相关文章
- 再谈System.arraycopy和Arrays.copyOf
之前转载过一篇博文,介绍过这两个方法,今天想要再次详细的了解一下. public static native void arraycopy(Object src, int srcPos, Object ...
- System.BadImageFormatException”C#报错
在平常的开发中或多或少会遇到一些问题,而本次向小编这里是自己刚刚解决的一个问题,贴出来与大家分享一下,纠结了一个下午,终于解决了,是有关平台的一个报错问题. 方法/步骤 报错”“Syste ...
- 沉淀再出发:再谈java的多线程机制
沉淀再出发:再谈java的多线程机制 一.前言 自从我们学习了操作系统之后,对于其中的线程和进程就有了非常深刻的理解,但是,我们可能在C,C++语言之中尝试过这些机制,并且做过相应的实验,但是对于ja ...
- .net应用程序安装部署时异常 Error 1001. 在初始化安装时发生异常 System.BadImageFormatException:未能加载文件或程序集 的解决办法【成功解决】
采用.net 4.0框架开发的一个桌面应用程序在某学校的一体机(Windows7的32位操作系统)上做安装部署时抛出异常,安装程序回滚,多次尝试仍不成功. Error 1001. 在初始化安装时发生异 ...
- 多线程003 - 再谈CyclicBarrier
java.util.concurrent.CyclicBarrier也是JDK 1.5提供的一个同步辅助类(为什么用也呢?參见再谈CountDownLatch).它同意一组线程互相等待,直到到达某 ...
- 再谈CLR查找和加载程序集的方式
原文:再谈CLR查找和加载程序集的方式 这是一个老问题,以前也有朋友写过一些文章介绍,但可能还不是很全面.我也多次被人问到,这里结合案例再次谈谈,希望对大家有所帮助. 本文范例代码可以通过这里下载 h ...
- Java继承之再谈构造器
目录 Java继承之再谈构造器 初始化基类 默认构造器 带参数的构造器 子类调用父类构造器 Java继承之再谈构造器 初始化基类 前面提到,继承是子类对父类的拓展.<Thinking in Ja ...
- Java再谈方法
1.3再谈方法 1.3.1 什么是方法(函数) ①方法是类或对象行为特征的抽象,也称为函数. ②Java里的方法不能独立存在,所有的方法必须定义在类里. 修饰符 返回值类型 方法名(参数类型 形参1, ...
- [转载]再谈百度:KPI、无人机,以及一个必须给父母看的案例
[转载]再谈百度:KPI.无人机,以及一个必须给父母看的案例 发表于 2016-03-15 | 0 Comments | 阅读次数 33 原文: 再谈百度:KPI.无人机,以及一个必须 ...
随机推荐
- 启动Sonar报错,ERROR: [1] bootstrap checks failed [1]: system call filters failed to install
错误提示信息: ERROR: [1] bootstrap checks failed[1]: system call filters failed to install; check the logs ...
- SAP销售订单需求类型的确定优秀级
需求类型的确定优秀级:1.策略组里的需求类型:2.MRP组里的:3.SO行项目类别+MRP类型4.SO行项目类别 部分截图:
- 关于vs无法创建虚拟目录的问题
插入链接:https://blog.csdn.net/zhao1955/article/details/92182935 补充:改完之后不要忘记以管理员的身份运行vs
- c#---Socean.RPC框架实测[并发量13w][响应时间0.04ms]
目录1.高性能RPC框架:Socean.RPC 前言 经过一段时间的优化,Socean.RPC的性能又提高了一些,不过这差不多是socketAPM模型的极限了.本框架仅仅2000多行代码,无第三方框架 ...
- RocketMQ原理及源码解析
RocketMQ原理深入: 一.定义: RocketMQ是一款分布式.队列模型的消息中间件,有以下部分组成: 1.NameServer: 一个几乎无状态的节点,可集群部署,节点之间无任何信息同步 2. ...
- 【JVM学习笔记一】Java内存区域
1. 运行时数据区域 1) 程序计数器 | 线程私有,存储线程运行时所执行字节码的行号,实现分支.循环.跳转.异常处理.线程恢复等基础功能 | Java方法,记录正在执行的虚拟机字节码指令的行号:Na ...
- FreePascal - CodeTyphon 和 Lazarus, 如何像Delphi一样有代码之间的连线?
CodeTyphon 6.9 默认CodeTyphon没有开启代码之间连线功能,一直不知道如何调出来,在使用CodeTyphon 和 Lazarus 很渴望也能像Delphi那样有这种功能,实际上它们 ...
- .NET编译问题汇总
1.Your project.json doesn't list 'win' as a targeted runtime. You should add '"win": { }' ...
- TensorFlow NMT的数据处理过程
在tensorflow/nmt项目中,训练数据和推断数据的输入使用了新的Dataset API,应该是tensorflow 1.2之后引入的API,方便数据的操作.如果你还在使用老的Queue和Coo ...
- Mysql 游标初识
MySql 游标初识 认识 游标(cursor), 按字面意思可理解为, 游动的标识, 或者叫做"光标", 这样更容易理解. 就好比现有一张表存储了n行记录, 然后我想每次取出一行 ...