再谈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.无人机,以及一个必须 ...
随机推荐
- 报错 xxx@1.0.0 dev D:\> webpack-dev-server --inline --progress --configbuild/webpack.dev.conf.js
是因为node_modules有意外改动,导致依赖库不完整. 解决:1.删除项目下的node_modules,在你的项目目录下 重新执行npm install,这会重新生成node_modules, ...
- - XML 解析 总结 DOM SAX PULL MD
目录 目录 XML 解析 总结 DOM SAX PULL MD 几种解析方式简介 要解析的内容 DOM 解析 代码 输出 SAX 解析 代码 输出 JDOM 解析 代码 输出 DOM4J 解析 代码 ...
- mycat在windows环境下安装和启动
1.下载从如下地址下载mycat的安装包: http://www.mycat.io/ eg:Mycat-server-1.6.6.1-release-20181031195535-win.tar.gz ...
- mvn clean -U -e -B -X的作用 查看详细出错信息
https://blog.csdn.net/u014515854/article/details/79820497 在持续集成服务器上使用怎样的 mvn 命令集成项目,这个问题乍一看答案很显然 ...
- .Net Core 指定编码格式的问题
我们在读取txt文件时,如果文件格式不是utf8,则获取的中文会乱码,所以要么另存文件为utf8格式,要么使用和文件相同的编码来读取. 如果文件为utf8,则: //一种 StreamReader s ...
- 关于springMVC中的路径问题
相对路径中,我们最后想要的到的是绝对路径,而绝对路径=参照路径+相对路径: 相对路径往往都知道,只需要区分参照路径即可:对于前台和后台,参照路径不太相同: 什么是前台,后台路径: 前台路径: 出现在 ...
- if控制器,如何传参。
- 2019-07-30 ThinkPHP文件上传
文件上传就是获取到待上传文件的临时路径,把它移动到服务器下的相应文件夹中. 文件上传,必须在表单中的form标签中写入:enctype="multipart/form-data" ...
- 下拉菜单旋转出现css
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- 从 Vue 的视角学 React(一)—— 项目搭建
虽然 Vue 在国内一家独大,但在全球范围内,React 依然是最流行的前端框架 最近和一些朋友聊天,发现很多项目都选择了 React 技术栈,而且公司的新项目也决定使用 React 我一直以来都是走 ...