How can I treat MSB3245 (could not resolve reference) warning as an error?

前端 未结 2 1387
执念已碎
执念已碎 2020-11-27 07:56

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.

相关标签:
2条回答
  • 2020-11-27 08:46

    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";
      }
    }
    
    0 讨论(0)
  • 2020-11-27 08:57

    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

    0 讨论(0)
提交回复
热议问题