67 votes

TFS 2012 Build "Accès au chemin d'accès refusé".

J'utilise TFS 2012 Build et je rencontre une erreur

L'accès au chemin est refusé

La solution en cours de construction contient environ 15 projets dont un certain nombre utilise l'assemblage Castle.Components.Validator.2.5.0.

J'ai vu d'autres articles qui parlent des erreurs TFS Build Access Denied, mais ils font généralement référence à l'exécution simultanée de plusieurs builds. Dans ce cas, un seul build est exécuté à la fois. De plus, l'erreur se produit lorsque le serveur est redémarré ou que la compilation n'a pas été exécutée depuis un certain temps.

Une fois qu'un build est exécuté et échoue, le suivant réussit et chacun d'entre eux réussit à nouveau jusqu'à ce que le build n'ait pas été exécuté pendant un certain temps ou que le serveur soit redémarré. Bien que nous puissions contourner ce problème, il s'agit d'un casse-tête manuel.

Voici l'erreur :

C:\WINDOWS\Microsoft.NET\Framework64\v4.0.30319\Microsoft.Common.targets (3513) : Impossible de copier le fichier " D:\Builds\12\Foo\Check -Dans le bâtiment \Sources\packages\Castle.Components.Validator.2.5.0\lib\NET40\Castle.Components.Validator.dll " à " D:\Builds\12\Foo\Check -Dans le bâtiment \Binaries\Castle.Components.Validator.dll ".

Accès au chemin ' D:\Builds\12\Foo\Check -Dans le bâtiment \Binaries\Castle.Components.Validator.dll est refusé.

En regardant le fichier journal, vous pouvez voir que le build essaie de copier le fichier deux fois. Comme le premier a un verrou sur le fichier, le second échoue et donc le build échoue. Voici un extrait du fichier journal qui montre ce qui se passe :

2>_CopyFilesMarkedCopyLocal : Copie du fichier de " D:\Builds\12\Foo\Check -Dans le bâtiment \Sources\packages\Castle.Components.Validator.2.5.0\lib\NET40\Castle.Components.Validator.dll " à " D:\Builds\12\Foo\Check -Dans le bâtiment \Binaries\Castle.Components.Validator.dll ".

5>_CopyFilesMarkedCopyLocal : Copie du fichier de " D:\Builds\12\Foo\Check -Dans le bâtiment \Sources\packages\Castle.Components.Validator.2.5.0\lib\NET40\Castle.Components.Validator.dll " à " D:\Builds\12\Foo\Check -Dans le bâtiment \Binaries\Castle.Components.Validator.dll ".

2>_CopyFilesMarkedCopyLocal : Copie du fichier de " D:\Builds\12\Foo\Check -Dans le bâtiment \Sources\packages\MvcContrib.Mvc3.FluentHtml -ci.3.0.96.0 \lib\MvcContrib.FluentHtml.dll " à " D:\Builds\12\Foo\Check -Dans le bâtiment \Binaries\MvcContrib.FluentHtml.dll ". Copie du fichier de " D:\Builds\12\Foo\Check -Dans le bâtiment \Sources\packages\RhinoMocks.3.6\lib\Rhino.Mocks.dll " à " D:\Builds\12\Foo\Check -Dans le bâtiment \Binaries\Rhino.Mocks.dll ".

Toute aide sur la façon de résoudre ce problème serait grandement appréciée.

51voto

Mike Asdf Points 536

Comme d'autres l'ont mentionné, cela se produit lorsque l'on effectue des constructions multithreads avec un répertoire de destination commun et que la tâche de copie de fichier rencontre un conflit simultané avec une tâche de copie exécutée pour un autre projet.

Normalement, cela devrait donner lieu à une exception "fichier utilisé par un autre processus" (qui est traitée et relancée par la tâche de copie de fichier), mais parfois l'opération sur le fichier donne lieu à une exception "Accès refusé". (Je ne sais toujours pas pourquoi)

Certains suggèrent de "résoudre la duplication", mais je ne pense pas que cela soit réalisable dans les cas où tous les projets doivent faire directement référence à une bibliothèque comme log4net.

Évidemment, une façon d'éviter ce problème est d'exécuter explicitement msbuild avec /p:BuildInParallel=false o /m:1 o /maxcpucount:1 (ou omettre complètement l'argument) pour forcer le mode single-threaded.

Cependant, dans TFS 2013 le modèle de construction par défaut passe toujours automatiquement /m (utiliser tous les cœurs) à msbuild, qui remplace silencieusement tout paramètre de single-thread que vous pouvez passer manuellement. (Déterminé par ma propre expérimentation et l'examen des journaux de diagnostic)

Une autre solution de contournement que j'ai essayée était de passer manuellement /p:AllowedReferenceRelatedFileExtensions=none à msbuild, qui empêche tous les fichiers pdb et xml d'être copiés à partir des bibliothèques référencées. (Pendant un certain temps, je n'ai vu que des fichiers xml avoir ce problème.) Mais ensuite, j'ai continué à avoir des problèmes avec log4net.dll.

L'ultime solution de contournement que j'ai utilisée est celle que j'ai découverte en décompilant le code source pour Microsoft.Build.Tasks.Copy :

if (hrForException == -2147024891)
{
    if (!Copy.alwaysRetryCopy)
        throw;
    else
        this.LogDiagnostic("Retrying on ERROR_ACCESS_DENIED because MSBUILDALWAYSRETRY = 1", new object[0]);
}

Si l'erreur -2147024891 (0x80070005 access is denied) se produit, la tâche de copie vérifie une variable spéciale pour savoir si elle doit réessayer. Cette valeur est définie par une variable d'environnement :

Copy.alwaysRetryCopy = Environment.GetEnvironmentVariable("MSBUILDALWAYSRETRY") != null;

Après avoir défini la variable d'environnement MSBUILDALWAYSRETRY = 1 (et redémarré le serveur de compilation), le problème a disparu. Et J'ai également commencé à voir périodiquement des avertissements "Retrying on ERROR_ACCESS_DENIED..." dans les journaux de compilation, prouvant que le paramètre prenait effet (au lieu que les compilations réussissent simplement par coïncidence).

(Notez que cette variable d'environnement n'est pas bien documentée, utilisez-la comme il convient).

Mise à jour : Apparemment TFS 2015 ne remplace plus votre /m:1 avec /m (même sur les définitions de build legacy/XAML), ce qui devrait permettre à /m:1 Encore une fois, une solution valable.

2 votes

TfvcTemplate.12.xaml semble fonctionner avec /m:1 mais pas avec /p:BuildInParallel=false

2 votes

Ce piratage de MSBUILDALWAYSRETRY est dégoûtant, mais au moins il me permet de savoir que MS en a autant marre que moi de ces bêtises et qu'il n'y a effectivement rien qui m'échappe. Il est temps d'ajouter une autre étape à ma liste de contrôle de démarrage du serveur de construction.

0 votes

J'ai utilisé MSBUILDALWAYSRETRY = 1 et maintenant j'obtiens "Exceeded retry count of 10. Échec". Des indices ?

42voto

Buck Hodges Points 766

Il semble qu'il y ait deux projets qui copient le même fichier. Selon le moment, ils se produisent parfois en même temps, ce qui entraîne l'échec. Vous devez retracer l'identifiant du nœud pour trouver le projet source. Voir http://blogs.msdn.com/b/buckh/archive/2012/01/21/a-tool-to-find-duplicate-copies-in-a-build.aspx pour plus de détails et un code qui pourrait vous permettre de le retrouver.

6 votes

Buck - Merci pour votre réponse rapide. Votre commentaire et votre lien ont été utiles pour comprendre le problème. L'ancien serveur de compilation que nous utilisions n'était pas un serveur multiprocesseur et la compilation ne fonctionnait donc qu'avec un seul processeur. Notre nouveau serveur de build est multi-proc et maintenant les builds s'exécutent sur plusieurs processeurs ce qui conduit à la collision de fichiers. Dans ce cas particulier, il n'y a pas besoin d'accélérer la construction, donc j'ai changé le paramètre MSBuild Multi-Proc (sous Process/Advanced dans le Build Process Template) en False. Et en fait, cela a eu un impact imperceptible sur les performances de la construction.

3 votes

Une autre option dans ce cas, si j'avais besoin d'une capacité multiprocessus, est de savoir quels sont les projets qui partagent cette référence et de trouver une stratégie comme celle de définir les projets avec CopyLocal = False pour cet assemblage et d'utiliser un répertoire de dossiers partagés où les projets pourraient référencer l'assemblage à la place.

13voto

Ace Points 273

Comme Buck Hodges et Nimblejoe l'ont dit à juste titre, cela est principalement dû au fait que TFS exécute plusieurs processus MSBuild par défaut pour construire vos projets.

Vous pouvez l'écraser dans la définition de la construction en Processus -> 3. avancé -> Arguments MSBuild en ajoutant l'argument MSBuild /p:BuildInParallel=false

4 votes

@stuartd cela a été supprimé en 2013 TfvcTemplate.12.template garyhowlett.co.uk/2013/11/07/

1 votes

@felickz Le paramètre existe toujours si vous modifiez le modèle sous la rubrique Run MSBuild les paramètres de l'activité de construction (énumérés sous MSBuildMultiProc ).

11voto

StingyJack Points 10956

Cela peut également se produire si le dossier d'un agent de construction est ouvert.

1 votes

C'est un point mineur, mais je crois que ces erreurs se présentent comme "Folder was not empty" ou quelque chose de ce genre, plutôt que comme un accès refusé. C'est certainement une bonne chose à savoir, cependant.

0 votes

L'accès leur a été refusé pour le dernier scénario. Je m'en souviens parce que le même gars s'en est rendu compte 4 fois de suite et j'ai dû envoyer une note à l'équipe à ce sujet. Nous recevons aussi de temps en temps un "dossier non vide" aléatoire, mais ce n'est pas parce que quelqu'un a le dossier ouvert.

0 votes

Je me grattais la tête et j'ai réalisé que c'était la cause de mon problème.

0voto

Une cause possible est que si vous avez le bin o obj les dossiers des bibliothèques de classes archivées dans TFS. La suppression des dossiers bin ou obj des projets dans TFS résoudra ce problème si c'est le cas.

1 votes

Cela peut, et peut, se produire même sans vérifier les dossiers d'objets.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X