【问题标题】:Bizarre F# runtime error that happens in F#2 and not in F#3, also NUnit refuses to load an executable that runs发生在 F#2 而不是 F#3 中的奇怪 F# 运行时错误,NUnit 也拒绝加载运行的可执行文件
【发布时间】:2012-08-11 03:26:36
【问题描述】:

我重构了一个大型 F# 项目。它有一个自动构建命令,可以在 F# 编译器的一次长时间运行中编译所有源文件。这样我就可以轻松地进行可重现的构建。 buildcommand 在构建项目之前在自身上运行 nunit-console,这很好。重构后,我的大部分单元测试开始失败:

异常:System.BadImageFormatException:试图加载一个程序 格式不正确。 (HRESULT 异常:0x8007000B)

这是使用 F# 2.0 编译项目时,我可以从命令行重现相同的问题(即不使用 NUnit)。堆栈跟踪通常指向一段无害的新代码(一个只存储一些数据而没有做任何明显的事情的构造函数)。

但是,当使用 F# 3.0 编译项目时,在 F# 2.0 下遇到问题并且我尝试过的所有单元测试都通过了。这是从命令行调用时(不使用 NUnit)。 NUnit 现在声称我可以手动调用的新编译的可执行文件不存在。有一个很长的堆栈跟踪,顶部有文件未找到异常。 (我没有尝试使用 F# 3.0 构建 buildcommand,因此它的单元测试仍然可以正常运行也就不足为奇了)。

Google 建议 HRESULT: 0x8007000B 可能是由编译器错误引起的。这可能是一个糟糕的工匠指责他的工具的情况,但是当使用 F# 3.0 时问题就消失了。有人可以提出任何建议以尝试在 F# 2.0 下重新运行吗?

我对使用 F# 3.0 并不太担心。但我真的需要 NUnit 才能工作。有谁知道可能出了什么问题?重申一下,Nunit 无法加载从命令行启动时运行良好的可执行文件,但在使用 F# 2.0 而不是使用 F# 3.0 编译时从同一位置加载相同的可执行文件。

我将非常感谢您对此提供的任何帮助。非常感谢。

【问题讨论】:

    标签: f# nunit f#-3.0


    【解决方案1】:

    如果您尝试在 64 位进程中加载​​ 32 位程序集(反之亦然),我相信您也会收到此错误消息。您使用什么Platform Target 编译项目(通过项目属性窗格的“构建”选项卡设置)?

    我的猜测是您的项目设置或其他配置文件中存在一些混淆,导致 F# 2.0 编译器针对错误的平台目标进行编译。当 NUnit 尝试加载程序集时,它具有与 NUnit 程序集不同的“位数”——我相信 NUnit 程序集具有适用于 32 位和 64 位系统的特定版本——并最终崩溃。

    【讨论】:

    • 我似乎根本没有指定一个。但是,我认为这可能不是,因为大约 80% 的单元测试仍然通过。不管它是什么,整个东西都是在编译器的一次运行中编译的,所以不可能有一个以上的冲突平台。再加上它在重构之前运行良好,而我对构建系统没有做任何事情。很抱歉之前没有提到这一切。可能是因为存在一些这样的不匹配,F# 3.0 版本没有在 Nunit 中加载。请问有什么可以尝试的提示吗?
    • 这是我使用的命令行:'c:/Program Files (x86)/Microsoft F#/v4.0/Fsc.exe' -g --debug:full --tailcalls+ --target :exe --warn:4 --warnaserror:76 --LCID:1033 --utf8output --fullpaths --flaterrors --out:"..." --doc:"..." --lib:"。 .." --define:"DEBUG" --define:"TRACE" --reference:"FSharp.PowerPack.Parallel.Seq.dll" --reference:"nunit.framework.dll" --reference:"FsCheck. dll" --reference:"System.Xml.dll" --reference:"System.Xml.Linq.dll"(跟大量的.fs文件)
    • 你仍然可能有一个冲突的目标平台,即使整个东西在编译器的一次运行中被编译(即,到一个程序集中)。编译的程序集和 NUnit 之间会出现冲突 - 如果您的机器上有 64 位 NUnit 并尝试用它测试 32 位程序集,当 NUnit 尝试通过反射加载您的程序集时,它将崩溃并出现 BadImagePlatformException .
    • 在该命令行中,您没有指定目标平台。您需要像这样指定它:--platform:x86--platform:x64--platform:anycpu。我建议使用 AnyCPU,除非您特别需要针对 x86(32 位)或 x64(64 位)。
    • 我加了--platform:anycpu 没什么区别,可能是什么都不指定的时候是默认值。您是否碰巧知道是否有针对旧版本 .net 的命令行选项? GUI 以某种方式管理它,但命令行帮助没有提到任何类似的事情。非常感谢。
    【解决方案2】:

    这听起来可能是绑定重定向问题。当您调用 NUnit 时,您只是将 DLL/EXE 传递给它,还是将 .nunit 文件传递​​给它?在任何一种情况下,确保有一个对应的 .config 文件,其绑定重定向与您在 VS2012 中使用新的 ConsoleApplication 项目获得的绑定重定向相同(例如,重定向 FSharp.Core 2.0.0.0 -> 4.3.0.0 的那些,因为 powerpack 取决于前者,而你的 VS2012 盒子上有后者)。

    【讨论】:

    • 非常感谢您的回复。当我使用 GUI 时,确实有一个警告表明映射可能是问题。但是,测试在 GUI 中工作。 (即便如此,我目前正在考虑修复它。)但是,buildcommand 可以干净地编译项目而没有任何警告(使用 F#2 和 F#3)。鉴于缺乏警告,映射仍然是一个问题吗?再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-22
    • 1970-01-01
    相关资源
    最近更新 更多