卫星资源的.dll编译到了错误的.NET框架?

6
下面的程序应该从卫星资源文件中获取资源字符串。使用VS2015和目标框架 =“NET Framework 4.5.2”编译时,它运行良好。但是,将目标框架设置为“NET Framework 3.5”会导致它无法找到卫星资源文件并回退到默认资源。 我查看了.exe和卫星.dll文件,并发现它们编译为不同的.NET版本(尽管是生成它们的相同编译):
Main exe got:                  .Net Framework v3.5
Satellite resource dll got:    .Net Framework v4.0 

看起来卫星dll获得了错误的.Net版本。是否有人遇到过这种情况,并且有解决方法呢?(除了将项目升级到最新的.Net版本)

class Program
{
    static void Main(string[] args)
    {

        CultureInfo newCultureInfo = new System.Globalization.CultureInfo("da-DK");
        Thread.CurrentThread.CurrentUICulture = newCultureInfo;

        Console.WriteLine("Resource test");
        ResourceManager rm = new ResourceManager("ResourceTest.Resources.MyResources", Assembly.GetExecutingAssembly());

        Console.WriteLine(rm.GetString("hello"));

        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }
}

修改:看起来我的开发环境更新出了问题。重新安装整个计算机有所帮助,但仅仅重新安装 .Net 和 Visual Studio 是不够的!(我想知道注册表数据库中是否有一些内容没有被简单的重新安装重置)


不是常见的问题,唯一明显的原因是卫星dll没有被重建。更常见的问题是.resx文件仍然包含4.0类型引用。只有在对它们进行更改时才会被重写,而在更改框架目标后很容易忽略这一点。使用文本编辑器查看文件。 - Hans Passant
不,情况并非如此。我也考虑过这个问题,所以为了确保不是这种情况,我删除了整个bin目录,然后重新编译。但问题仍然存在。 - MadsN
我也遇到了这个问题。 - Peter Ittner
对我来说恰恰相反,它在我进行了干净的 Windows 安装之前是正常工作的,然后它开始为 .net 3.5 程序生成 .net 4.0 资源。因此,干净的安装可悲地不是解决方案/变通方法。 - hultqvist
2
尝试使用此解决方案,虽然它是针对VS2017的,但修复方法应该适用于类似情况。 - hultqvist
1个回答

1
我知道这个问题已经有将近六年的历史,但是在今天,使用Visual Studio 2019仍然存在此问题。我已经确认了16.10.2和16.10.3版本(可能还有更多)存在问题。构建一个.Net 3.5应用程序后,我发现资源dll无法工作,这让我感到困惑,直到我发现了你的问题,提示我需要调查资源dll的.Net版本,并发现这些确实与.Net 4 mscorlib相关联,而不是3.5。

问题确认

首先确认此问题。

  1. 在Visual Studio中,转到“工具/选项/项目和解决方案/构建和运行”,将MS Build项目生成输出详细程度设置至少为正常(默认为最小)。

  2. 重新生成你的.NET 3.5 项目。

  3. 在输出/生成窗口中查找任务GenerateSatelliteAssemblies:。下面的命令行显示了C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\al.exe,这是程序集链接器的.NET 4.8版本。在未受影响的系统上,应该是C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\al.exe

到目前为止,与 hultqvist's comment所提到的问题相同。然而,原因和解决方法不同。在我的系统上,那里提到的注册表键完全没有问题。

TL;DR - 解决方案(解决方法)

  1. 前往 C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(确切路径可能会因系统而异,例如 Professional 而非 Enterprise)。
  2. 创建该文件的备份副本。
  3. 编辑该文件,找到包含文本 _ALExeToolPath 的行。它应该在第 3739 行左右。看起来像这样:
    <PropertyGroup>
      <_ALExeToolPath>$(TargetFrameworkSDKToolsDirectory)</_ALExeToolPath>
      <_ALExeToolPath Condition="'$(PlatformTarget)' == 'x64'">$(TargetFrameworkSDKToolsDirectory)$(PlatformTarget)\</_ALExeToolPath>
    </PropertyGroup>
现在向下滚动到以下的AL标签,并找到SdkToolsPath属性。
    <AL AlgorithmId="$(Satellite_AlgorithmId)"
        BaseAddress="$(Satellite_BaseAddress)"
    ...
        SdkToolsPath="$(SdkToolsPathMaybeWithx64Architecture)"  <!-- this is incorrect -->
  1. 将属性的值从$(SdkToolsPathMaybeWithx64Architecture)更改为$(_ALExeToolPath)
  2. 保存文件(可能需要提权)
  3. 重新构建项目,将使用正确的链接器,您的资源dll将再次正常工作。

原因

此问题在此处引入以修复针对x64与x86的程序集链接器的一个小问题。如果您遵循该PR的评论线程,您会发现错误:在合并PR之前,实际上修复的变量已经更名,但他们忘记在AL属性中更新它。

因此,al.exe的sdk工具路径为空(它提到了一个不存在的变量),这导致msbuild始终调用默认值,通常是您系统上最新安装的框架sdk的x86版本,而不是与您的项目版本匹配的版本。

该版本的.targets文件已随VS更新一起推出。

此后,他们发现了这个错误并修复了它。截至今日,这个修复尚未推出。如果我正确理解了讨论的内容,它将在v16.11发布时推出。

如果您等不及,可以按照我上面描述的解决方法操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,