ResGen.exe错误:试图加载格式不正确的程序
更新:此问题已在中修复。净额4.5。一如既往,欢迎反馈!请在这篇博客帖子中留言,并报告任何错误微软连接。
最近,我们看到许多人报告了VisualStudio2010中的资源生成问题,特别是当他们瞄准目标时。NET Framework 3.5在64位计算机上运行。在这篇博客文章中,我将强调一个最常见的错误;它发生的时间和地点,以及如何解决它。在稍后的帖子中,我们将看看其他一些不太常见的错误,以及VS2008和VS2010的GenerateResource之间差异的一些背景。
样本错误:
ResourceForm.resx(1436,5):错误RG0000:无法加载文件或程序集'file:///C:/Users/sjoiner/Desktop/TestForm/ResTest/bin/x86/Debug/Foo.dll'或其依赖项之一。试图加载格式不正确的程序。第1436行,位置5。
发现此错误的情况:
必须满足以下所有条件:
- 64位操作系统
- 包含资源文件的项目(项目A)
- 项目A引用的程序集(程序集B)。这可以是第三方程序集,也可以是解决方案中通过项目对项目引用引用的另一个项目
- 项目A的一个或多个资源文件使用程序集B中的类型。例如,如果项目A是一个窗体,程序集B包含该窗体使用的控件。
- 下面标记为“X”的配置组合之一必须为true。 注:使用Visual Studio IDE生成等同于使用32位MSBuild.exe生成。
|
|
与2008年相比 |
与2010年相比目标为3.5或以下 |
VS2010版目标4.0 |
MSBuild.exe体系结构 |
32位
|
64位
|
32位
|
64位
|
32位
|
64位
|
组件B的架构 |
32位 |
|
X(X) |
X(X) |
X(X) |
|
X(X) |
64位 |
X(X) |
|
|
|
X(X) |
|
任何CPU |
|
|
|
|
|
|
解决方法1:
使您引用的程序集(程序集B)成为AnyCPU,而不是特定于体系结构。
赞成的意见:简单,意味着程序集B可以由任何引用程序集加载。
欺骗:如果您出于特定原因创建了引用架构特定的程序集,或者如果您引用的是3,则不可行第个特定于架构的政党集会。
关于解决方案2和3的说明:
变通方法2和3特别适用于项目目标设定的场景。NET 3.5具有引用32位程序集的.resx文件。除了更改为使用目标体系结构的MSBuild.exe之外,目前没有解决方案来针对4.0并尝试从64位MSBuild引用32位程序集或反之亦然。
请注意,通过强制ResGen.exe作为32位执行,实际上引入了相反的问题:如果您尝试在ResGen.exe中加载64位体系结构特定的引用程序集,则ResGen.exe现在将出错。
解决方法2:
通过以下方式将ResGen.exe设为32位:
1.Cd“%ProgramFiles(x86)%Microsoft SDKsWindows7.0ABin”
2.Corflags/32Bit+/强制ResGen.exe
然而,由于我们当前的生成过程有一个启发式方法,假设ResGen.exe是MSIL,仅执行上述步骤就会导致不同的错误(“指定的任务可执行文件”ResGen.exe“无法运行。句柄无效”)除非您通过将属性“ResGenToolArchitecture”设置为“Managed32Bit”来通知GenerateResource ResGen.exe现在是32位的。这可以通过执行以下操作之一来实现:
1.将<ResGenToolArchitecture>Managed32Bit</ResGenToolArchitecture>添加到生成资源目标的任何项目的项目文件中的PropertyGroup。NET 3.5–由于corflags技巧会在系统范围内影响ResGen.exe的位,因此必须为所有受影响的项目设置属性。
2.或者,如果直接运行MSBuild.exe,则使用全局属性开关传递它:“/p:ResGenToolArchitecture=Managed32Bit”
3.或在运行MSBuild.exe的命令窗口中或从以下位置打开VS 2010 IDE的命令窗口中将其设置为环境变量:“set RESGENTOOLARCHITECTURE=Managed32Bit”
赞成的意见:不需要更改引用程序集的体系结构
欺骗:更复杂;需要将解决方法烘焙到项目文件中,或烘焙到整个生成系统中。
解决方法3:
强制CLR加载全部的32位MSIL应用程序:
1.Cd“%windir%Microsoft.NETFramework64v2.0.50727”
2.Ldr64.exe setwow
然后,由于这也是一种强制ResGen.exe像执行32位进程一样执行的方法,因此还必须完成解决方案2的第二部分(设置ResGenToolArchitecture=Managed32Bit)。
赞成的意见:不需要更改引用程序集的体系结构
欺骗:影响CLR在整个计算机上的工作方式。还有与解决方案2相同的缺点。
说明:
每当试图加载与当前运行进程的体系结构不兼容的引用程序集时,就会出现此问题。由于框架引用程序集都是AnyCPU,因此可以由任何体系结构毫无问题地加载它们,因此当您有两个相互引用的特定于位的用户项目时,通常会发生这种情况,例如一个具有窗体,另一个实现控件,引用项目包含一个resx,该resx使用在引用项目中定义的类型。显然,如果您的项目引用特定于体系结构的第三方程序集,也会出现相同的问题。
这个问题也存在于VS 2008中,但不太明显,因为我们在一个典型的32位MSBuild.exe(存在64位MSBuildexe,但不经常使用)中生成了内部资源,为了注意到这个问题,用户必须引用一个特定的64位程序集;即便如此,一个简单的解决方法也应该是只使用64位MSBuild。
然而,在MSBuild 4.0中,由于我们在确定目标时使用ResGen.exe。NET 3.5或更低版本,并且由于ResGen.exe与关联。NET3.5是一个MSIL应用程序,现在任何目标都会出现此错误。NET 3.5在64位计算机上,并且有一个resx尝试从特定的32位程序集加载类型。
第一种解决方法通过将引用的程序集更改为可由任何应用程序加载来消除位不匹配。第二个和第三个解决方法通过将ResGen.exe设为32位来消除位不匹配,以便它可以成功加载32位程序集。
我希望这篇文章能让你更好地理解这个错误,并提供了解决它所需的工具。
萨拉·乔纳
MSBuild软件开发工程师