再谈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.无人机,以及一个必须 ...
随机推荐
- SpringBoot:3.SpringBoot使用Spring-data-jpa实现数据库访问
做Web开发,首先要能将数据渲染到网页中展示,其次是要获取数据库数据展示到视图层,在前面的文章SpringBoot整合Thymeleaf模板引擎渲染web视图,我们实现了从后端数据展示到视图层,那么下 ...
- sql中筛选第一条记录【分组排序】
问题描述 我们现在有一张表titles,共有4个字段,分别是emp_no(员工编号),title(职位),from_date(起始时间),to_date(结束时间),记录的是员工在某个时间段内职位名称 ...
- [Atcoder AGC032C]Three Circuits
题目大意:有一张$n$个点$m$条边的无向连通图,判断是否可以从中分出$3$个环,满足三个环覆盖整张图并且没有重复的边.$n,m\leqslant10^5$ 题解:分类讨论.有度数为奇肯定不行,因为连 ...
- 【题解】选数字 [51nod1354]
[题解]选数字 [51nod1354] 传送门:选数字 \([51nod1354]\) [题目描述] 共 \(T\) 组测试点,每一组给定一个长度为 \(n\) 的序列和一个整数 \(K\),找出有多 ...
- k8s-Namespace(命名空间)
k8s-Namespace(命名空间) Namespace(命名空间)是Kubernetes系统中的另一个非常重要的概念,通过将系统内部的对象“分配”到不同的Namespace中,形成逻辑上分组的不同 ...
- Kafka MirrorMaker 跨集群同步工具
一.MirrorMaker介绍 MirrorMaker是Kafka附带的一个用于在Kafka集群之间制作镜像数据的工具.该工具从源集群中消费并生产到目标群集.这种镜像的常见用例是在另一个数据中心提供副 ...
- Windwos利用批处理文件自动清理归档日志,计划任务
首先在X盘根目录建立一个文档 cmd.txt 打开cmd.txt这个文本文件,在里面第一行写入 DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-3'; ...
- 使用VBA将Excel指定单元格数据、字符串或者图表对象插入到Word模板指定书签处
准备工作: 1.首先需要提供一个word模板,并且标记好您要插入书签的位置,定义书签的命名.如图 2.模拟您要插入的Excel原始数据和图表对象 插入代码如下: Private Sub Command ...
- EntityFramework执行Add-Miragtion或者Update-Database出闲ScriptHalted
今天基友在他本机运行我的项目,执行ef还原数据的时候,一直出现ScriptHalted的错误. 找了下百度,只找到一个stackoverflowd的答案,没有看到中文的解决方案. 现在总结一下,并给出 ...
- js获取简单表单对象(1)
<form id="form"> <input type="text" name="username" value ...