Esto debería ser obvio para hacer, pero yo no podía hacer el trabajo…

Lo que yo estoy tratando de hacer es simple: me gustaría que mi compilación a fallar con un error si no hay una advertencia. Sí, el famoso TreatWarningsAsErrors

He configurado en mi proyecto de C# propiedades

El tratamiento de todas las advertencias de errores

Esto se traduce en la espera TreatWarningsAsErrors sección en mi csproj:

<TreatWarningsAsErrors>true</TreatWarningsAsErrors>

Hasta ahora tan bueno, si puedo añadir un inútil private variable en mi código, que se traduce en un error de compilación:

private int unused;

Error 3 Aviso de Error: El campo ‘XXXX.usado nunca es usado

Pero todo el problema es que yo no puede hacer que funcione para asamblea problemas de referencia. Si tengo una referencia a un desconocido de la asamblea, el compilador (ya sea devenv o msbuild) lanza una advertencia, pero quiero un error en su lugar.

Finalmente, estoy tratando de configurar una entrada validada en TFS configuración de compilación, por lo que TFS iba a rechazar una confirmación en caso de que haya un «El componente que se hace referencia ‘XXXX’ no se pudo encontrar.» advertencia. Algo más simple que la modificación de la plantilla de proceso de compilación sería genial.

InformationsquelleAutor ken2k | 2013-07-08

2 Comentarios

  1. 18

    MSBuild advertencias (todos empiezan con la MSB*) a diferencia de la CSC advertencias no puede ser suprimida ni promovido a errores. Por la razón de la ResolveAssemblyReference tarea imprime sus mensajes sobre la marcha y no agrega ninguna de ellas.

    La única solución viable es la lectura de la MSBuild archivos de registro creados durante la compilación de TFS.
    Creo que la solución más elegante es implementar una versión personalizada CodeActivity. La siguiente es una actividad sencilla que dará salida a los resultados de cualquier archivo que contenga una determinada SearchString:

    using System;
    using System.Activities;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using Microsoft.TeamFoundation.Build.Client;
    
    namespace MyBuildActivities.FileSystem
    {
        [BuildActivity(HostEnvironmentOption.Agent)]
        public sealed class ReadStringFromFile : CodeActivity
        {
            [RequiredArgument]
            public InArgument<IEnumerable<string>> Files { get; set; }
    
            [RequiredArgument]
            public InArgument<string> SearchString { get; set; }
    
            public OutArgument<string> Result { get; set; }
    
            protected override void Execute(CodeActivityContext context)
            {
                var files = context.GetValue(Files);
                var searchString = context.GetValue(SearchString);
    
                var list =
                    (files.Where(file => File.ReadAllText(file).Contains(searchString))
                        .Select(file => string.Format("{0} was found at {1}", searchString, file))).ToList();
    
                if(list.Count > 0)
                    Result.Set(context, string.Join(Environment.NewLine, list));
            }
        }
    }

    Declarado en el proceso de generación de la plantilla así:

    xmlns:cfs="clr-namespace:MyBuildActivities.FileSystem;assembly=MyBuildActivities"

    Invoca justo al final de la Compile and Test for Configuration secuencia:

    <Sequence DisplayName="Handle MSBuild Errors">
             <Sequence.Variables>
                     <Variable x:TypeArguments="scg:IEnumerable(x:String)" Name="logFiles" />                                                                                                                 
                     <Variable x:TypeArguments="x:String" Name="readStringFromFileResult" />
             </Sequence.Variables>
             <mtbwa:FindMatchingFiles DisplayName="Find Log Files" MatchPattern="[String.Format(&quot;{0}\**\*.log&quot;, logFileDropLocation)]" Result="[logFiles]" mtbwt:BuildTrackingParticipant.Importance="Low" />
             <cfs:ReadStringFromFile Files="[logFiles]" SearchString="MSB3245" Result="[readStringFromFileResult]" />
             <mtbwa:WriteBuildMessage DisplayName="Write Result" Message="[readStringFromFileResult]" Importance="[Microsoft.TeamFoundation.Build.Client.BuildMessageImportance.High]" />
             <If Condition="[readStringFromFileResult.Count > 0]" DisplayName="If SearchString Was Found" mtbwt:BuildTrackingParticipant.Importance="Low">
                     <If.Then>
                              <Throw DisplayName="Throw Exception" Exception="[New Exception(readStringFromFileResult)]" mtbwt:BuildTrackingParticipant.Importance="Low" />
                     </If.Then>
             </If>                                                                                                              
    </Sequence>

    He probado esto en TFS 2012 a pesar de que se debe trabajar para TFS 2010.

    • Eso es lo que me temía… entiendo advertencias de MSBuild sí mismo no puede ser promovido a errores. Lo que yo no entiendo es por qué un desconocido de la asamblea de referencia no es un CSC de advertencia. De todos modos, de una actividad personalizada de hecho es el camino a seguir, incluso si a primera vista suena un poco excesivo para el (aparentemente) simple caso de uso que tenía. +1, gracias por tu respuesta.
    • Para hacer la solución, publicado por KMoraz trabajo que había que hacer lo siguiente: 1. Agregar cadena vacía, el Resultado en el CodeActivity si la cadena no se encontró en los archivos. 2. Cambio readStringFromFileResult.Contar a readStringFromFileResult.De longitud en la construcción de la plantilla. De lo contrario me gustaría obtener una excepción nula cuando la cadena no se encontró.
  2. 12

    MSBuild 15 admite ahora una /warnaserror bandera, que las fuerzas de MSBuild advertencias a ser tratados como errores.

    MSBuild 15 es instalado con Visual Studio 2017, pero también puede ser descargar desde GitHub

    Este problema de GitHub explica por qué no puede ser establecido a través de un MSBuild propiedad (tl;dr de una propiedad es demasiado tarde)

Dejar respuesta

Please enter your comment!
Please enter your name here