今天,当我们继续学习.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的更多相关文章

  1. 再谈System.arraycopy和Arrays.copyOf

    之前转载过一篇博文,介绍过这两个方法,今天想要再次详细的了解一下. public static native void arraycopy(Object src, int srcPos, Object ...

  2. System.BadImageFormatException”C#报错

    在平常的开发中或多或少会遇到一些问题,而本次向小编这里是自己刚刚解决的一个问题,贴出来与大家分享一下,纠结了一个下午,终于解决了,是有关平台的一个报错问题.   方法/步骤     报错”“Syste ...

  3. 沉淀再出发:再谈java的多线程机制

    沉淀再出发:再谈java的多线程机制 一.前言 自从我们学习了操作系统之后,对于其中的线程和进程就有了非常深刻的理解,但是,我们可能在C,C++语言之中尝试过这些机制,并且做过相应的实验,但是对于ja ...

  4. .net应用程序安装部署时异常 Error 1001. 在初始化安装时发生异常 System.BadImageFormatException:未能加载文件或程序集 的解决办法【成功解决】

    采用.net 4.0框架开发的一个桌面应用程序在某学校的一体机(Windows7的32位操作系统)上做安装部署时抛出异常,安装程序回滚,多次尝试仍不成功. Error 1001. 在初始化安装时发生异 ...

  5. 多线程003 - 再谈CyclicBarrier

      java.util.concurrent.CyclicBarrier也是JDK 1.5提供的一个同步辅助类(为什么用也呢?參见再谈CountDownLatch).它同意一组线程互相等待,直到到达某 ...

  6. 再谈CLR查找和加载程序集的方式

    原文:再谈CLR查找和加载程序集的方式 这是一个老问题,以前也有朋友写过一些文章介绍,但可能还不是很全面.我也多次被人问到,这里结合案例再次谈谈,希望对大家有所帮助. 本文范例代码可以通过这里下载 h ...

  7. Java继承之再谈构造器

    目录 Java继承之再谈构造器 初始化基类 默认构造器 带参数的构造器 子类调用父类构造器 Java继承之再谈构造器 初始化基类 前面提到,继承是子类对父类的拓展.<Thinking in Ja ...

  8. Java再谈方法

    1.3再谈方法 1.3.1 什么是方法(函数) ①方法是类或对象行为特征的抽象,也称为函数. ②Java里的方法不能独立存在,所有的方法必须定义在类里. 修饰符 返回值类型 方法名(参数类型 形参1, ...

  9. [转载]再谈百度:KPI、无人机,以及一个必须给父母看的案例

    [转载]再谈百度:KPI.无人机,以及一个必须给父母看的案例 发表于 2016-03-15   |   0 Comments   |   阅读次数 33 原文: 再谈百度:KPI.无人机,以及一个必须 ...

随机推荐

  1. springboot yml配置文件注入值

    1.编写javabean: package com.example.springboot.bean; import org.springframework.boot.context.propertie ...

  2. Orleans 3.0 为我们带来了什么(转载)

    以下为本篇文章的 作者: 艾心 出处: https://www.cnblogs.com/edison0621/ 原文:https://devblogs.microsoft.com/dotnet/orl ...

  3. kubernetes(k8s) Prometheus+grafana监控告警安装部署

    主机数据收集 主机数据的采集是集群监控的基础:外部模块收集各个主机采集到的数据分析就能对整个集群完成监控和告警等功能.一般主机数据采集和对外提供数据使用cAdvisor 和node-exporter等 ...

  4. 第一章 Maven 安装配置

    Maven基于(POM)项目对象模型,通过一小段描述信息来管理项目的构建.文档.和报告的项目管理软件,类似于php 的管理构建工具composer. 有关详细的Maven学习,可以参考学习https: ...

  5. vue-awesome-swiper兼容ie9

    轮播插件vue-awesome-swiper在ie9中运行的时候没效果 解决方法: vue-awesome-swiper在IE9下报错, 主要原因是element.classlist.add()方法在 ...

  6. 25、vuex改变store中数据

    以登录为例: 1.安装vuex:npm install vuex --save 2.在main.js文件中引入: import store from '@/store/index.js'new Vue ...

  7. js 对象克隆方法总结(不改变原对象)

    1.通用对象克隆: function clone(obj){ let temp = null; if(obj instanceof Array){ temp = obj.concat(); }else ...

  8. AF step、Bokeh等说明

    基本概念:FV: Focus Value, 用来衡量图像AF的清晰度. DOF: Deep Of Field, 景深,表示物距清晰的范围,景深越长表示物距前后清晰的范围越大. AF step一般来说, ...

  9. 一次 Young GC 的优化实践(FinalReference 相关)

    本文转载自公众号:涤生的博客,阅读时间大约需要11分钟.涤生的文章看起来跟破案一样,很精彩,很有启发. 前言 博客已经好久没有更新了,主要原因是 18 年下半年工作比较忙,另外也没有比较有意思的题材, ...

  10. 安装socketio出现module 'importlib._bootstrap' has no attribute 'SourceFileLoader' 错误

    安装socketio出现module 'importlib._bootstrap' has no attribute 'SourceFileLoader' 错误 执行: pip install --u ...