Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Satellite resource .dll's compiles to wrong .net framework?

The program below is supposed to get a resource string from a satellite resourcefile. It works fine when compiled with target framework='NET Framework 4.5.2' using VS2015. However, setting target framework='NET Framework 3.5' makes it unable to find the satellite resource file and fall back to the default resources.

I peeked in the .exe and satellite .dll files and found that they are compiled to different .net versions (Eventhough it was the same compilation that generated them):

Main exe got:                  .Net Framework v3.5
Satellite resource dll got:    .Net Framework v4.0 

It seams like the satellite dlls gets the wrong .Net version. Has anyone experienced this and is there a solution? (Other than upgrading the project to the newest .Net version)

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();
    }
}

EDIT: Seams like I got a bad update to my development enviroment. A reinstall of the whole computer helped, but simply reinstalling .Net and Visual Studio didn't! (I wonder if there is something in the registry database that doesn't get reset by a simple reinstall)

like image 904
MadsN Avatar asked Nov 21 '22 05:11

MadsN


1 Answers

I know this question is almost six years old but this is again an issue today, with Visual Studio 2019. I have confirmed it with 16.10.2 and 16.10.3 (may be more). Building a .Net 3.5 application left me with non-working resource dll's, which puzzled me until I found your question that hinted to investigate the resource dll .Net version, discovering that these were indeed linked to .Net 4 mscorlib instead of 3.5.

Problem confirmation

First confirm the issue.

  1. In Visual Studio, go to Tools / Options / Projects and Solutions /
    Build and Run and set MS Build project build output verbosity to at least Normal (default is Minimal).

  2. Rebuild your .Net 3.5 project.

  3. In the Output / Build window look for the task GenerateSatelliteAssemblies:. The command line below shows C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\al.exe, which is the .Net 4.8 version of the assembly linker. On an unaffected system, that should have been C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\al.exe.

So far the same problem as mentioned in the link by hultqvist's comment on the question. The cause and solution is different, however. The registry keys that are mentioned there, were perfectly fine on my system.

TL;DR - Solution (Workaround)

  1. Go to C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets (exact path may differ a bit on your system, e.g. Professional instead of Enterprise).
  2. Create a backup copy of this file.
  3. Edit the file, and find a line containing the text _ALExeToolPath. It should be around line 3739. Looks like this:
    <PropertyGroup>
      <_ALExeToolPath>$(TargetFrameworkSDKToolsDirectory)</_ALExeToolPath>
      <_ALExeToolPath Condition="'$(PlatformTarget)' == 'x64'">$(TargetFrameworkSDKToolsDirectory)$(PlatformTarget)\</_ALExeToolPath>
    </PropertyGroup>
  1. Now scroll a bit down into the AL tag below and find the SdkToolsPath attribute.
    <AL AlgorithmId="$(Satellite_AlgorithmId)"
        BaseAddress="$(Satellite_BaseAddress)"
    ...
        SdkToolsPath="$(SdkToolsPathMaybeWithx64Architecture)"  <!-- this is incorrect -->
  1. Change the value of the attribute from $(SdkToolsPathMaybeWithx64Architecture) to $(_ALExeToolPath)
  2. Save the file (needs elevation, probably)
  3. Rebuild your project, the correct linker is used and your resource dll's will work again.

Cause

This issue was introduced here to fix a minor issue with the assembly linker when targeting x64 vs x86. If you follow the comment thread with that PR you will spot the mistake: the actual variable in the fix is renamed after discussion, but they forgot to update that in the AL attribute before the PR was merged.

Because of this, the sdk tools path for al.exe is empty (it mentions a non-existing variable) and that causes msbuild to always call the default, which is usually the x86 version of the newest installed framework sdk on your system -- instead of a version that matches the version of your project.

That version of the .targets file has been rolled out with a VS update.

They have since then spotted the mistake and fixed it. That fix has not rolled out as of today. If I understand the discussion correctly it is targeted for publish with v16.11.

If you cannot wait for that, follow the workaround I described above.

like image 75
M-Peror Avatar answered Jan 20 '23 10:01

M-Peror