6

We have a .Net 3.5 application that is built using some scripts that call msbuild.exe

Recently all our machines started automatically updating from .Net 4.0 to .Net 4.5 as part of a company-wide policty, and our build scripts started failing.

The errors given is that they cannot find a referenced assembly, like this :

error CS0012: The type 'System.Drawing.Image' is defined in an assembly that is not referenced. 
You must add a reference to assembly 'System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.

It looks like in every case, we try to build project A that has a reference to project B, and project B has a reference to library X, and get an error that project A needs a reference to library X.

A temporary workaround is to uninstall 4.5, uninstall 4.0, then re-install 4.0, however this is time consuming and not practical in an environment where updates are often silent and automatic.

I've tried using the following msbuild switches already, with no luck

  • /toolsversion:3.5 - Exception about Func being undefined
  • /toolsversion:4.0 - Does not work because 4.5 replaced 4.0 tools
  • /p:TargetFrameworkVersion="v3.5" - Same error
  • /p:VisualStudioVersion=11.0 - Same error *` in the csproj file - Already exists, and same error

The .csproj files already has <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> specified in every single csproj file in my solution, and ToolsVersion="4.0".

I have also tried changing the TargetFrameworkVersion to 4.0, and that does not work either.

I found some notes online about Microsoft changing the flag OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration from false to true during the 4.0 to 4.5 update, however manually setting that flag in the csproj files also does not fix the issue.

<OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration>
    false
</OnlyReferenceAndBuildProjectsEnabledInSolutionConfiguration>

Why is msbuild failing to find these child assemblies after upgrading from 4.0 to 4.5, and how can I fix it?

Update

I've finally figured out the source of the problem, but I have no idea how this could be happening.

ProjectA has a class which inherits from an abstract class in ProjectB, and one of the properties of ProejctB.BaseClass is of type System.Drawing.Image.

namespace ProjectA
{
    public class SomeClass : BaseClass { }
}

namespace ProjectB
{
    public abstract class BaseClass
    {
        public System.Drawing.Image GetImage() { };
    }
}

From everything I've read online, and from creating a test project of my own, this means that ProjectA needs a reference to System.Drawing.Image in order to build.

But for whatever reason, this restriction does not seem to matter for our project when buliding with msbuild 4.0 or in VS 2010. It's perfectly happy to build ProjectA without a reference to System.Drawing.Image.

Even after updating to .Net 4.5, I can still build ProjectA successfully from Visual Studio 2010 without adding a reference to System.Drawing.Image, however building using msbuild now (correctly?) fails. I also get the reference errors when building in VS 2012 Express, so whatever is allowing this to occur has apparently been fixed in newer versions of VS.

For now, I have gone through all 148 projects in our solution and fixed all the references, however I want to leave this question open to try and get an answer on why I am able to build ProjectA using msbuild 4.0 or Visual Studio 2010 without a reference to System.Drawing.Image.

I have already determined that I can't easily reproduce the behavior in a test project, so my best guess is its either some configuration, some part of the build scripts, or it's a bug that existed back when the .sln or .csproj files got created and no longer exists with newly created projects.

Rachel
  • 130,264
  • 66
  • 304
  • 490
  • 1
    From a MS PSS Developer standpoint, you need to get a small bare bones example that reproduces the issue. Chances are when you do this, you will see the delta yourself. If you still dont see the root cause in the bare bones solution then log a support case as this smells of a bug (and if it is, troubleshooting will come under free support). One hint is if it compiles in VS2010 and fails in 2012, check what versions of DLLs are loaded in the Modules window... Good luck!! – Jeremy Thompson Nov 06 '14 at 10:58
  • @JeremyThompson I have been trying to reproduce the problem in a small sample solution, but have had no luck so far. The application is very large, a few years old, and was created before I joined the team. In addition, the original person who created it is no longer around for me to ask if he did anything unusual with the setup. I believe you're right that it is most likely a bug, however will double-check the dll versions too. Thank you. – Rachel Nov 06 '14 at 14:42
  • Have you tried reading VS2010 build log to see what switches does it pass to MSBuild so it compiles fine? – BartoszKP Nov 10 '14 at 16:34
  • @BartoszKP Yes, if you view my [question history](http://stackoverflow.com/revisions/26638992/8) you'll see more details. I removed it since it didn't seem relevant however can re-add it if you think it matters. The `msbuild.exe` script is the same, however the `csc.exe` generated had one difference - a [/highentropyva-](http://bit.ly/1xmGdec) flag. It doesn't seem relevant, and it still fails to build when I run it manually, regardless of what I set the flag to or if I include it or not. The references generated for `csc.exe` are the same, and do not include a reference to `System.Drawing` – Rachel Nov 10 '14 at 19:07
  • 5
    This doesn't have anything to do with MSBuild, what changed is that you are using a different C# compiler. Version 5 instead 4. I've seen cursory evidence in other questions that is is more aggressive about wanting to resolve indirect type references. Nothing to nail to the wall, everybody just fixes this with the obvious solution. Getting hung up on this is silly, just add the reference. – Hans Passant Nov 10 '14 at 19:09
  • 2
    @HansPassant I agree, it's best just to fix the problem. I was just curious what (bug?) was allowing this to build in the first place. I'm pretty sure you're right about it being a change in the C# compiler though. Thanks. – Rachel Nov 10 '14 at 19:35
  • Congrats on halve a million points @HansPassant, IMHO you should post your comment here as and answer. – Jeremy Thompson Nov 11 '14 at 15:12

4 Answers4

1

Based on Hans' comment, it sounds like something changed in the internal C# compiler between version 4 and version 5 to fix the bug that was allowing us to build ProjectA without proper references.

This doesn't have anything to do with MSBuild, what changed is that you are using a different C# compiler. Version 5 instead 4. I've seen cursory evidence in other questions that is is more aggressive about wanting to resolve indirect type references. Nothing to nail to the wall, everybody just fixes this with the obvious solution.

When viewing the msbuild.exe log, I can see it comes down to a call to csc.exe, which contains the exact same /reference list, however fails with 4.5.

Building ProjectA with 4.0

Task "Csc"
  c:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /errorreport:prompt /warn:4 /define:TRACE /reference:C:\Path\bin\Release\ProjectB.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Data.DataSetExtensions.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Web.Services.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Xml.Linq.dll" /debug:pdbonly /filealign:512 /keyfile:ProjectA.snk /optimize+ /out:obj\Release\ProjectA.dll /target:library Properties\AssemblyInfo.cs SomeFile.cs Properties\VersionInfo.cs
  Microsoft (R) Visual C# 2010 Compiler version 4.0.30319.1
  Copyright (C) Microsoft Corporation. All rights reserved.

Done executing task "Csc".

Building ProjectA with 4.5

Task "Csc" (TaskId:5812)
  C:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /noconfig /nowarn:1701,1702 /nostdlib+ /errorreport:prompt /warn:4 /define:TRACE /highentropyva- /reference:C:\Path\bin\Release\ProjectB.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Core.dll" /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Data.DataSetExtensions.dll" /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Web.Services.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.5\System.Xml.Linq.dll" /debug:pdbonly /filealign:512 /keyfile:ProjectA.snk /optimize+ /out:obj\Release\ProjectA.dll /target:library /utf8output Properties\AssemblyInfo.cs SomeFile.cs Properties\VersionInfo.cs (TaskId:5812)
  Microsoft (R) Visual C# Compiler version 4.0.30319.18408 (TaskId:5812)
   (TaskId:5812)
  for Microsoft (R) .NET Framework 4.5 (TaskId:5812)
  Copyright (C) Microsoft Corporation. All rights reserved. (TaskId:5812)
   (TaskId:5812)
SomeFile.cs(32,18): error CS0012: The type 'System.Drawing.Image' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. [C:\Path\ProjectA.csproj]
  c:\Path\bin\Release\ProjectB.dll: (Location of symbol related to previous error) (TaskId:5812)
  The command exited with code 1. (TaskId:5812)
Done executing task "Csc" -- FAILED. (TaskId:5812)

I was hoping someone here would be able to explain what that was, and how I could reproduce this "bug" with 4.0, however it doesn't look like this question is an easy one to answer.

Community
  • 1
  • 1
Rachel
  • 130,264
  • 66
  • 304
  • 490
  • We're currently experiencing similar issues on our build server after updates were installed. The issue unfortunately only becomes apparent when the apps start and immediately die of linker errors. I've found that the way references are treated has changed. If you add a NuGet reference in VS, its properties are set to copy local, but the related True tag isn't added to the .csproj file. Before the update the referenced assemblies were copied to the output directory anyway; now they aren't. Transitive references aren't copied at all. – bstenzel Nov 17 '14 at 11:06
0

If I had to guess, I'm going to say that all the references that it can no longer locate are version 2.0.0.0. We had a similar issue here recently where we had to update the references to be for 4.0.0.0 versions of System.* and mscorlib and similar references.

If you cannot replace the references and BindingRedirects aren't an option, try adding v2.0.0.0 manually to your bin folder.

Lastly, you can make your build output verbose to see where it's looking for these references, it might guide you to find a solution.

Steve Lillis
  • 3,263
  • 5
  • 22
  • 41
0

Perhaps when it updates its not updating your Runtime Settings Schema, specifically the <probing> Element that tells .Net what paths to search for assemblies:

Eg.

<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <probing privatePath="bin;bin2\subbin;bin3"/>
      </assemblyBinding>
   </runtime>
</configuration>

See: http://msdn.microsoft.com/en-us/library/microsoft.build.tasks.assignprojectconfiguration.onlyreferenceandbuildprojectsenabledinsolutionconfiguration%28v=vs.121%29.aspx

0

Rachel, any chance references on your System.Drawing on projects are set to SpecificVersion = true after the upgrade?

Also, are you using any precompiled resx files in your library projects? Try right-clicking the .resx file and choosing 'Run Custom Tool' again to redo the references.

And for last of my attempts to help you, you could try using the useLegacyV2RuntimeActivationPolicy="true" on your main project configuration and try to use the legacy System.Drawing library.

rodrigogq
  • 1,943
  • 1
  • 16
  • 25
  • The `System.Drawing` reference in `ProjectB` is set to whatever the defaults are... in the .csproj file it just says ``. There is no "Specific Version" property in VS like non-system references have. ProjectB isn't the problem though, it's ProjectA, which is allowed to compile without a reference to `System.Drawing`, even though it should have one. Also, we are not using any precompiled resx files, although I'm not sure why that would matter. And I'll look into where that property is and give it a try, although once again I don't think it'd matter – Rachel Nov 11 '14 at 15:54
  • I tried to help using [this article](http://msdn.microsoft.com/en-us/library/cc668079%28v=vs.100%29.aspx). It sure is weird that your msbuild is trying to use a `System.Drawing version = 2.0`. – rodrigogq Nov 11 '14 at 16:14
  • Thanks for the link, I'll check it out too. We're building for .Net 3.5, which is why we're using `System.Drawing` v2.0. If I recall correctly, the next version is 4.0, which would require that we update our entire application to 4.0 which is not an option at this time. – Rachel Nov 11 '14 at 16:15