web-dev-qa-db-fra.com

Visual Studio reconstruit les projets non modifiés

Ainsi, comme l’indique le titre, j’ai une solution VS2010 contenant environ 50 projets. Si je modifie un projet "de niveau supérieur" auquel rien ne fait référence, VS reconstitue néanmoins les 50 projets. J'exécute Visual Studio 2010 Ultimate sans aucun add-on. J'utilise ILMerge pour consolider tous les projets dans un seul fichier.

J'ai vérifié cela en vérifiant les horodatages des dlls de niveau inférieur et je constate qu'ils sont effectivement reconstruits même si leur code n'a pas été touché.

J'ai lu toutes les réponses et commentaires pour:

Visual Studio 2008 continue de reconstruire

Visual studio continue de tout construire

Un problème de compilation VS2010 étrange se produit dans ma solution

Motifs de reconstruction des projets C # dans Visual Studio

Mais la plupart d'entre eux ne font que suggérer des projets de déchargement pour accélérer les temps de construction, mais rien de concret quant à une solution. J'essaie de comprendre pourquoi VS pense que ces projets dépendants doivent être reconstruits alors que ce n'est pas le cas, et qu'il faut y remédier.

J'ai activé "Outils> Options> Projets et solutions> Construire et exécuter> Construire uniquement les projets de démarrage et les dépendances lors de l'exécution", mais sans effet.

De plus, si je reconstruis simplement un projet de "niveau intermédiaire" qui ne comporte que 8 dépendances directes (in), il génère toujours les 8 projets, même si ILMerge n'est pas appelé et qu'aucun des projets dépendants n'a été modifié.

Merci à tous pour vos idées.

Ajoutée

Pour tester certaines des suggestions, j'ai créé un nouveau projet WinForms à partir de zéro. J'ai ensuite créé deux nouveaux projets dans cette solution. J'ai copié tout le code et les ressources (pas le fichier de projet) de mes deux projets de niveau le plus bas dans les deux nouveaux projets (je l'ai fait en déposant les fichiers et les dossiers d'Explorer dans le projet dans Visual Studio).

Le projet le plus bas, appelons-le B, ne fait référence à aucun autre projet. Le projet suivant, A, n'est référencé que B. Donc, une fois que j'ai ajouté les références .NET et Assembly requises aux projets, la solution était construite.

J'ai ensuite eu ma nouvelle référence de projet WinForm A et fait une construction complète. La chaîne de référence est donc:

WinForm -> A -> B

J'ai ensuite modifié WinForm _ ​​uniquement et réalisé une construction standard (F6). Comme auparavant, Visual Studio a reconstruit les trois projets.

Après une éleminiation systématique des fichiers source dans le projet B, j’ai trouvé que si je supprimais mes Resources.Designer.cs et Resources.resx (et commentais le code qui utilisait l’objet .Properties.Resources de ces ressources), une modification de WinForm ne reconstruirait plus la solution complète et ne reconstruirait que WinForm.

Ajouter les Resources.resx et Resources.Designer.cs au projet B (en laissant le code référencé mis en commentaire afin que rien ne fasse appel aux ressources) réintroduirait le comportement de génération complet.

Pour voir si mes fichiers de ressources étaient endommagés, je les ai de nouveau supprimés, puis créé un nouveau (via Propriétés du projet -> Ressources) et rajouté la même ressource qu'auparavant, à savoir un fichier Excel unique. Avec cette configuration, la reconstruction complète aurait toujours lieu.

J'ai ensuite supprimé la ressource unique, mais j'ai laissé le fichier de ressource dans le projet B. Même en l'absence de ressources ajoutées, mais le fichier de ressources toujours dans le projet, la reconstruction complète (inutile) se produirait.

Il semble que le simple ajout d'un fichier de ressources à un projet (.NET 3.5) oblige Visual Studio 2010 à toujours reconstruire ce projet. Est-ce un bug ou un comportement prévu/attendu?

Merci encore à tous!

64
Matt Klein

Bien que je ne pense pas que ce soit une solution, c'est une solution de contournement qui a fonctionné pour ma situation ...

Au départ, environ 5 projets sur 50 contenaient une section Resources. Ces projets seraient toujours reconstruits et par conséquent, tout ce dont ils dépendaient serait également reconstruit. L'un de ces 5 projets était une bibliothèque de "base" référencée par 48 autres projets. Ainsi, 96% de mon projet serait reconstruit à chaque fois, même s'il n'en avait pas besoin.

Ma solution consistait à utiliser une injection de dépendance, des interfaces et un projet "Ressources" dédié. Au lieu que ces 5 projets référencent leur propre objet Resources, j'ai créé une interface dans chaque projet qui fournirait les ressources souhaitées. Ensuite, les classes ayant besoin de ces ressources nécessiteraient que l'interface soit transmise lors de leur création dans le constructeur (injection de constructeur).

J'ai ensuite créé un projet "Ressources" distinct qui comportait une section Ressources comme d'habitude. Ce projet contenait uniquement les ressources elles-mêmes et une classe pour chaque interface nécessaire pour fournir ces ressources via une interface. Ce projet référencerait tout autre projet dépendant des ressources et implémenterait l'interface dont il avait besoin.

Enfin, dans mon projet "Top Level" auquel rien ne faisait référence (et où le fichier exe était réellement construit et la racine de ma composition vivante), je faisais référence au projet "Resources", connectais la DI et partais.

Cela signifie que seuls deux projets (les "Ressources" et le "Niveau supérieur") seront reconstruits à chaque fois, et si je construis une construction partielle (Shift-F6), ils ne seront pas reconstruits du tout.

Encore une fois, ce n’est pas un travail génial, mais avec 48 projets construits chaque fois qu’une construction prend environ 3 minutes, je perdais donc 30 à 90 minutes par jour avec des reconstructions inutiles. Il a fallu un certain temps pour le refactoriser, mais je pense que c'était un bon investissement.

Voici un schéma simplifié. Notez que les dépendances de Main.exe à Proj1 et Proj2 ne sont pas affichées afin de réduire l'encombrement.

Diagram of solution

Avec cette conception, je peux créer un Proj1 ou un Proj2 sans déclencher une reconstruction complète, car ils n'ont aucune dépendance sur une section Resources. Seule Main connaît l’implémentation de Resources.

17
Matt Klein

Ouvrez Outils - Options, sélectionnez Projets et solutions - Créer et exécuter dans l’arborescence, puis définissez "Verbosité de sortie du projet MSBuild" sur Diagnostic . Le motif de la création du projet, c.-à-d.

Le projet 'ReferencedProject' n'est pas à jour. Elément de projet "c:\some.xml" a l'attribut "Copier dans le répertoire de sortie" défini sur "Copier toujours'.

ou

Le projet 'MyProject' n'est pas à jour. Fichier d'entrée 'c:\ReferencedProject.dll' est modifié après le fichier de sortie 'c:\MyProject.pdb'.

Dans ce cas, le correctif consiste à copier some.xml uniquement s'il est plus récent.

Les événements pré et post-construction peuvent également déclencher la construction.

112
user3285954

Cela se produit lorsqu'un projet contient un fichier qui n'existe pas vraiment.
Le projet ne peut pas déterminer si le fichier a été modifié (car il n’y est pas), il est donc reconstruit. 

Il suffit de regarder tous les fichiers du projet et de rechercher celui qui n’a pas de flèche extensible à proximité.

15
Yochai Timmer

J'ai eu le même problème dans VS 2015.

Qu'est-ce que le truc pour moi est:

  1. Un projet faisait référence à une copie dans une autre corbeille de projets (magique, oui). Ce genre de choses peut être trouvé lors du passage à la sortie de diagnostic (dans les options de construction), puis à la tentative de construire des projets un par un à partir de la hiérarchie des projets. références.
  2. J'ai changé tous les fichiers "Copier toujours" dans tous les projets en "Copier si plus récent". En gros, dans tous les fichiers .csproj, remplacez <CopyToOutputDirectory>Always</CopyToOutputDirectory> par <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  3. Ensuite, j'ai désactivé le tunnel NTFS comme décrit dans this article avec ce script PowerShell:

New-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "MaximumTunnelEntries" -Value 0 -PropertyType "DWord"

Après cela, j’avais besoin de reconstruire et cela semble fonctionner pour le moment.

9
Michael Logutov

Dans mon cas, le coupable était le paramètre "Copier en local" d'une dll référencée définie sur true et "Copier dans le répertoire de sortie" en définissant un fichier défini sur Copier toujours.

4
I-A-N

J'ai eu ce même problème et il s'est avéré être lié à un couple de projet qui avait une référence de copie locale à une DLL dans leur propre répertoire de sortie.

Pour y parvenir, il était essentiel de définir une sortie de diagnostic pour la sortie de génération, mais également de savoir ce qu'il fallait rechercher dans le journal. Recherche de: ' pas à jour ' était la clé.

1
Ademund

J'ai finalement trouvé un dernier coupable que j'ai eu du mal à trouver en augmentant la verbosité du journal de construction.

Dans certains cas, MSBuild recherche vc120.pdb dans le dossier de sortie et, si ce fichier n'existe pas, le projet entier sera reconstruit. Cela se produit même si vous avez désactivé la génération de symboles de débogage

La solution de contournement consiste à activer les symboles de débogage et laisser ce fichier généré, puis à désactiver à nouveau le paramètre sans supprimer le fichier PDB.

1
Mehrdad

Pour cette catégorie de problèmes de construction, définir la verbosité de sortie de MSBuild sur 'diagnostic' est en effet une première étape nécessaire. La plupart du temps, la raison indiquée pour les reconstructions serait suffisante pour agir, MAIS occasionnellement, MSBuild affirmerait à tort que certains fichiers sont modifiés et doivent être copiés.

Si tel est le cas, vous devez désactiver le tunneling NTFS ou dupliquer votre dossier de sortie vers un nouvel emplacement. La voici en plus de mots.

0
Ofek Shilon

Dans mon cas (solution mixte C #, C++/CLI et solution C++ native), certains projets C++ étaient liés de nouveau, même si rien n’avait changé. J'ai passé des siècles à essayer de comprendre ce qui se passait. Finalement, à partir de l'option "Ligne de commande", j'ai déterminé que le chemin de sortie de PDB (option/Fd) ne pouvait pas gérer le paramètre de dossier $ (IntDir). J'ai enlevé cela - une valeur vide fera la valeur par défaut correctement - et mon problème est parti.

0
user11657883

D'après vos observations, il semble que vos projets expriment des dépendances par rapport à d'autres projets d'une manière qui ne soit pas évidente. Il est possible que des dépendances orphelines restent dans les fichiers de projet sans être apparentes dans l'interface utilisateur. Avez-vous parcouru un fichier de projet défectueux après l'avoir ouvert dans un éditeur de texte? Dépendances de construction de solutions vérifiées?

Si vous ne trouvez rien, essayez de recréer l’un de vos projets pour voir si le nouveau projet présente le même problème. Si le projet propre se construit correctement, vous saurez que vous avez des dépendances indésirables exprimées quelque part. Autant que je sache, ceux-ci devraient figurer dans le ou les fichiers de projet ou dans le fichier de solution, sauf si vous avez des makefiles ou d'autres étapes de construction inhabituelles.

0
Owen Wengerd

Voici une réponse de VS2010 reconstruit toujours la solution?

Ce problème est résolu en modifiant les fichiers du projet, la solution de nettoyage, supprimer tous les dossiers bin à la main, redémarrer Visual studio et tout reconstruire.

0
Ryan Byrne

J'ai eu le problème de la reconstruction de projets Visual Studio lors de la mise à niveau de Visual Studio 2015 à 2017 et j'ajoute cette réponse à l'intention des personnes susceptibles de rencontrer des problèmes similaires, car cela ne semble pas être documenté nulle part.

Dans mon cas, le problème était que tous les projets de la solution avaient le même chemin de sortie intermédiaire (obj). Le fichier GeneratedInternalTypeHelper.cs est généré par tous les projets contenant XAML. Jusqu'à Visual Studio 2015, le processus de construction ne vérifiait apparemment pas la date de fichier de ce fichier et ne rencontrait donc aucun problème. Avec VS2017, la date de fichier de ce fichier est vérifiée et, du fait qu'un projet ultérieur du processus de construction l'écrase (avec le même contenu), le projet précédent reconstruit, générant à nouveau le déclenchement de la construction ultérieure, à l'infini.

Dans ce cas, la solution consiste à s'assurer que tous les projets ont des répertoires de sortie intermédiaires différents, ce qui éliminera le problème.

0
Flash

Un autre problème qui se produit fréquemment est lorsqu'un élément de votre solution a un tampon modifié qui sera utilisé à l'avenir. Cela peut arriver si vous réglez votre horloge en avant, puis réglez votre horloge sur la bonne heure. J'ai eu cela se produire lors de l'installation de Linux.

Dans ce cas, vous pouvez toucher tous les fichiers de manière récursive avec git bash (oui, sous Windows):

find . -exec touch {} \;
0
Mikhail

J'avais les mêmes problèmes avec vous… .. J'ai découvert que cela provenait de fichiers supprimés… .. Lorsque j'ai supprimé les fichiers de mon projet, les problèmes avaient disparu….

0
PhonPanom