web-dev-qa-db-fra.com

Traitez tous les avertissements comme des erreurs

Cela devrait être évident à faire, mais je ne pouvais tout simplement pas le faire fonctionner ...

Ce que j'essaie de faire est simple: je voudrais que ma compilation échoue avec une erreur s'il y a un avertissement. Oui, le célèbre TreatWarningsAsErrors...

Je l'ai configuré dans mes propriétés de projet C #

treat warnings as errors

Il en résulte la section TreatWarningsAsErrors attendue dans mon csproj:

<TreatWarningsAsErrors>true</TreatWarningsAsErrors>

Jusqu'ici tout va bien, si j'ajoute une variable private inutile dans mon code, cela entraîne une erreur de compilation:

private int unused;

Erreur 3 Avertissement en tant qu'erreur: le champ "XXXX.unused" n'est jamais utilisé

Mais tout le problème est que je ne peux pas le faire fonctionner pour problèmes de référence de l'assembly. Si j'ai une référence à un assembly inconnu, le compilateur (devenv ou msbuild) envoie un avertissement, mais je veux une erreur à la place.

En fin de compte, j'essaie de configurer une configuration de construction TFS d'enregistrement sécurisé, afin que TFS rejette une validation en cas de " Le composant référencé 'XXXX' est introuvable. "avertissement. Quelque chose de plus simple que de modifier le modèle de processus de construction serait génial.

42
ken2k

Les avertissements MSBuild (tous commencent par MSB *) par opposition aux avertissements CSC ne peuvent pas être supprimés ni promus en erreurs. Pour cette raison, la tâche ResolveAssemblyReference imprime ses messages à la volée et n'en agrège aucun.

La seule solution possible consiste à lire les fichiers journaux MSBuild créés lors de la génération TFS. Je pense que la solution la plus élégante est d'implémenter une build personnalisée CodeActivity . Ce qui suit est une activité simple qui produira les résultats de tout fichier contenant un SearchString donné:

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

Déclaré dans le modèle de processus de génération comme suit:

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

Appelé juste à la fin du Compile and Test for Configuration séquence:

<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>

J'ai testé cela sur TFS 2012, mais cela devrait également fonctionner pour TFS 2010.

19
KMoraz

MSBuild 15 prend désormais en charge un /warnaserror flag, qui force les avertissements MSBuild à être traités comme des erreurs.

MSBuild 15 est installé avec Visual Studio 2017 mais peut également être téléchargé depuis GitHub

Ce problème GitHub explique pourquoi il ne peut pas être défini via une propriété MSBuild (tl; dr une propriété est trop tard)

13
Richard Szalay