11

My question is based on another one, but I want to do the opposite: tell msbuild to treat the warning as an error instead of suppressing a specific msbuild warning.

However, all I see so far says /p:WarningsAsErrors only takes in csc warnings and errors. I tried just dropping the MSB and googling for what number might go in there to work, but no luck.

Is there any way to treat an "assembly reference not found" warning from msbuild (command line) as an error?

Community
  • 1
  • 1
Maslow
  • 18,464
  • 20
  • 106
  • 193

2 Answers2

9

Recently I needed something similar (acting on certain log events) but I couldn't find a clean solution mainly because I haven't figured out how to programmatically access the loggers in the msbuild process. I did come up with this though, adapted to your problem the principle is:

  • install a custom logger scanning for the warning
  • build
  • set a static flag if the warning occurs
  • have a custom task check that flag and raise an error if it's on

Might sound hard, but the code is simple enough:

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Foo
{
  public static class Common
  {
    public static bool errorsOccurred = false;
  }

  public class ScanLogger : Logger
  {
    public override void Initialize( IEventSource eventSource )
    {
      eventSource.MessageRaised += ( s, e ) =>
        Common.errorsOccurred |= e.Message.Contains( "MSB3245" );
    }
  }

  public class CheckErrors : Task
  {
    public override bool Execute()
    {
      if( Common.errorsOccurred == false )
        return true;
      Log.LogError( "errorsOccurred = true" );
      return false;
    }
  }
}

Here's a sample msbuild script using it:

<UsingTask TaskName="Foo.CheckErrors" AssemblyFile="Foo.dll"/>

<Target Name="MyBuild">
  <Message Text="MSB3245"/> <!-- simulate the build warning -->
  <Foo.CheckErrors /> <!-- this will trigger an error -->
</Target>

And you invoke it like this:

msbuild /logger:Foo.dll my.proj

edit I just needed this again but couldn't find the original dll nor project file etc anymore - I figured storing just the code and simplest build instructions in git and building it on the fly when needing it is probably cleaner. So basically store the code above in a file customlogger.cs and then somewhere in your build process, before effectively invoking msbuild with the custom logger, build it using

<Target Name="BuildCustomLoggerDll">
  <Csc Sources="$(MSBuildThisFileDirectory)customlogger.cs"
       References="System.dll;mscorlib.dll;Microsoft.Build.Framework.dll;Microsoft.Build.Utilities.v4.0.dll"
       TargetType="Library" OutputAssembly="$(MSBuildThisFileDirectory)CustomLogger.dll"/>
</Target>

update In response to comments: trying this again today I'm not sure the original code actually ever worked (well, it does for the sample message shown but not for actual warning MSB3245), since it hooks message events only whereas the ResolveAssemblyReference emits an actual warning event and moreover the warning number isn't typically contained contained in the message. This does the trick though:

public class ScanLogger : Logger
{
  public override void Initialize( IEventSource eventSource )
  {
    eventSource.WarningRaised += ( s, e ) => Common.errorsOccurred |= e.Code == "MSB3245";
  }
}
stijn
  • 34,664
  • 13
  • 111
  • 163
  • is there a way to add this process to the solution level instead of the project level? – Maslow Feb 24 '14 at 16:18
  • Basically you'd define this logic in a common file and then import that file it in each project. Not sure about the best way to do this automatically on a solution basis though, something like this maybe: http://stackoverflow.com/questions/18249027/import-targets-file-from-command-line-in-msbuild or http://dotnet.geir-sorensen.net/2010/04/msbuild-custom-targets.html – stijn Feb 24 '14 at 19:51
  • @stijn I am using this code, and got it working with your example (where I artificially send a message containing MSB3245). However, when I run it for real, no such message comes in. I am logging (to a file) every message received by this logger, and no interesting ones come in (with warnings, etc.). I also tried to hook into eventSource.AnyEventRaised and eventSource.WarningRaised, but they don't have the warning I'm trying to find either. It looks like the behavior has changed. – fastmultiplication Feb 22 '18 at 23:30
  • @fastmultiplication what version are you using? – stijn Feb 23 '18 at 11:37
  • @stijn my msbuild version is 15.5.180.51428 – fastmultiplication Feb 23 '18 at 18:51
  • @fastmultiplication you're right, doesn't work, but see update which does – stijn Feb 24 '18 at 10:45
1

It seems that the message associated with this warning that's not a warning:

If this reference is required by your code, you may get compilation errors

, is not quite correct. If the missing reference is a WPF theme, you'll get a run-time error (System.IO.FileNotFoundException) instead.

As an aside, if you specifically look for MSB3245 you'll get:

CSC : warning CS1691: 'MSB3245' is not a valid warning number

Michael J.
  • 349
  • 1
  • 10