web-dev-qa-db-fra.com

"Le type de fournisseur CodeDom Microsoft.VisualC.CppCodeProvider est introuvable" exception lors de la génération d'une application Web dans le serveur de génération

Je suis en train de construire/emballer une application Web dans un serveur de build et cela échoue avec l'exception suivante:

Erreur ASPNETCOMPILER ASPCONFIG: Le type de fournisseur CodeDom "Microsoft.VisualC.CppCodeProvider, CppCodeProvider, Version = 10.0.0.0, Culture = neutre, PublicKeyToken = b03f5f7f11d50a3" ne peut pas être . .

Le serveur de compilation:

  • Windows Server 2008 R2 Standard
  • TeamCity 8.0.4
  • .NET 4.5
  • Kit de développement logiciel (SDK) Windows pour Windows 7 et .NET 4
  • Kit de développement logiciel (SDK) Windows pour Windows 8 et .NET 4.5
  • Bibliothèque de classes portable
  • ASP MVC 4

L'application est une application Web MVC 4 ASP, ciblant .NET 4.5.

La configuration de construction consiste à construire la solution avec MSBuild, ce qui permet le déploiement dans un package afin que je puisse le publier ultérieurement. 

Dans le journal de TeamCity, je peux voir que l'erreur survient lorsque MSBuild exécute "aspnet_compiler.exe".

Les constructions sans problème dans ma machine de développement et peuvent également le publier sur un IIS local sans problèmes.

Est-ce que quelqu'un sait ce qui peut causer ce problème?

UPDATE

Voir ma réponse ci-dessous.

14
Arthur Nunes

Pour moi, cette erreur se produisait dans VS2017 lors de la construction du projet Web. Le correctif consistait à masquer le répertoire node_modules dans l'explorateur de fichiers. Apparemment, cela empêche le compilateur ASP.NET d'analyser tous ces fichiers et empêche ainsi l'erreur.

40
Vanitas1440

Ce message m'a fourni un indice important: apparemment, la précompilation ASP.NET analyse le projet et les fichiers de sortie et tente de compiler chaque fichier source trouvé, malgré son langage (voir ici ). 

Dans ce cas, mon application Web dépend d'un projet qui inclut des dll non gérées dans un fichier ".h". Ces fichiers sont copiés dans le répertoire de sortie ("Copier si plus récent") afin que je puisse le nommer au moment de l'exécution.

Il semble que la précompilation ASP.NET trouve le ".h" et essaie de le compiler, même s’il n’est pas nécessaire. Et, à mon avis, cela échoue car mon serveur de génération ne dispose pas des outils nécessaires (il semble que CppCodeProvider est fourni avec le kit de développement .NET 2.0 ).

Lorsque j'ai modifié le projet pour ne pas copier ces fichiers dans le répertoire de sortie, la construction s'est bien déroulée. J'ai également testé la copie des fichiers, mais avec "PrecompileBeforePublish" défini sur false dans le profil de publication, et cela a également fonctionné.

Maintenant, j'ai quelques options, mais je ne les aime pas:

  • Désactivez "PrecompileBeforePublish". Je crois que le principal inconvénient de cette situation est que l'expérience des utilisateurs de l'application sera plus lente lors de l'accès au premier site.

  • Essayez d'exclure des fichiers du dossier de sortie et ajoutez-les à nouveau après la pré-compilation. Cela semble beaucoup de travail pour quelque chose que je ne devrais pas m'inquiéter en premier lieu.

  • Essayez de dire à "aspnet_compiler.exe" d’exclure les fichiers/dossiers incriminés lors de l’exécution. Je ne sais pas comment utiliser le profil de publication, car je ne contrôle que "PrecompileBeforePublish". En outre, il semble que "aspnet_compiler.exe" n'offre pas cette option ( ici et ici ).

Je pense que pour le moment je vais désactiver "PrecompileBeforePublish", car cela semble être une voie rapide avec peu de mises en garde. Mais je pense qu’il devrait exister un meilleur moyen de le gérer, en excluant les dossiers ou les types de fichiers de la précompilation à l’aide du profil de publication.

21
Arthur Nunes

Cela a commencé à se produire lors de la mise à jour de VS2017. Le problème pour moi était node.js. Si je supprimais le dossier node_modules, le projet serait construit sans erreur. Il s'avère que changer la valeur de MvcBuildViews en false dans le fichier csproj comme suggéré par anders ici le corrige. Ce n’est pas idéal, car les vues mvc ne seront pas compilées tant que IIS ne les aura pas rendus. Personnellement, je cache juste le dossier node_modules pour résoudre le problème, mais je voulais ajouter cette réponse au cas où cela aiderait à éclaircir le problème sous-jacent pour quelqu'un d'autre.

<MvcBuildViews>false</MvcBuildViews>

Dans mon scénario, je dois envoyer un interpréteur Perl avec mon site Web ASP.Net (ne demandez pas pourquoi j'ai besoin de Perl, et je suis désolé de le faire à l'avance!), Y compris les fichiers .c qui ont provoqué aspnet_compiler. exe à l'erreur, comme d'autres ont mentionné être leur problème. Le répertoire Perl est dans mon dossier bin et est requis au moment de l'exécution.

Le problème que j'ai rencontré était lorsque vous attrib +H le dossier, il a bien été ignoré par aspnet_compiler, mais ne se trouvait pas dans mon dossier de sortie de publication. J'ai donc dû le pirater encore plus en cachant le dossier, compiler les vues, afficher le dossier, puis copier le dossier au bon endroit. Cela impliquait de modifier la tâche AspNetPreCompile originale. Voir ci-dessous:

<!-- Overwrite AspNetPreCompile task because it was trying to compile .c files found in the Perl directory. This prevents that but still copies Perl to publish file. -->
<!-- Taken from: C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\VisualStudio\v15.0\Web\Transform -->
<Target Name="AspNetPreCompile" DependsOnTargets="$(AspNetPreCompileDependsOn)"  Condition="'$(AspNetPreCompile)' != 'false'">

    <PropertyGroup  Condition="'$(UseMetabasePath)' == 'true'" >
        <_PreAspnetCompileMergeSingleTargetFolderFullPath></_PreAspnetCompileMergeSingleTargetFolderFullPath>
        <_AspNetCompilerVirtualPath></_AspNetCompilerVirtualPath>
    </PropertyGroup>
    <PropertyGroup  Condition="'$(UseMetabasePath)' != 'true'" >
        <_PreAspnetCompileMergeSingleTargetFolderFullPath>$([System.IO.Path]::GetFullPath($(_PreAspnetCompileMergeSingleTargetFolder)))</_PreAspnetCompileMergeSingleTargetFolderFullPath>
    </PropertyGroup>

    <PropertyGroup>
        <_PostAspnetCompileMergeSingleTargetFolderFullPath>$([System.IO.Path]::GetFullPath($(_PostAspnetCompileMergeSingleTargetFolder)))</_PostAspnetCompileMergeSingleTargetFolderFullPath>
    </PropertyGroup>

    <!-- Modification #1. -->
    <Exec Command="attrib +H &quot;$(IntermediateOutputPath)AspnetCompileMerge\Source\bin\Perl&quot;" />

    <AspNetCompiler
        PhysicalPath="$(_PreAspnetCompileMergeSingleTargetFolderFullPath)"
        TargetPath="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)"
        VirtualPath="$(_AspNetCompilerVirtualPath)"
        Force="$(_AspNetCompilerForce)"
        Debug="$(DebugSymbols)"
        Updateable="$(EnableUpdateable)"
        KeyFile="$(_AspNetCompileMergeKeyFile)"
        KeyContainer="$(_AspNetCompileMergeKeyContainer)"
        DelaySign="$(DelaySign)"
        AllowPartiallyTrustedCallers="$(AllowPartiallyTrustedCallers)"
        FixedNames="$(_AspNetCompilerFixedNames)"
        Clean="$(Clean)"
        MetabasePath="$(_AspNetCompilerMetabasePath)"
        ToolPath="$(AspnetCompilerPath)"
        />

    <!-- Modification #2. -->
    <Exec Command="attrib -H &quot;$(IntermediateOutputPath)AspnetCompileMerge\Source\bin\Perl&quot;" />

    <!--
        Removing APP_DATA is done here so that the output groups reflect the fact that App_data is
        not present
        -->
    <RemoveDir Condition="'$(DeleteAppDataFolder)' == 'true' And Exists('$(_PostAspnetCompileMergeSingleTargetFolderFullPath)\App_Data')"
                Directories="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)\App_Data" />


    <CollectFilesinFolder Condition="'$(UseMerge)' != 'true'"
        RootPath="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)" >
        <Output TaskParameter="Result" ItemName="_AspnetCompileMergePrecompiledOutputNoMetadata" />
    </CollectFilesinFolder>

    <ItemGroup Condition="'$(UseMerge)' != 'true'">
        <FileWrites Include="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)\**"/>
    </ItemGroup>

    <!-- Modification #3. -->
    <ItemGroup>
        <Perl Include="$(IntermediateOutputPath)AspnetCompileMerge\Source\bin\Perl\**\*.*" />
    </ItemGroup>

    <!-- Modification #4. -->
    <Copy SourceFiles="@(Perl)" DestinationFolder="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)\bin\Perl\%(RecursiveDir)"></Copy>

</Target>

NE MODIFIEZ PAS le fichier .targets d’origine, copiez-le dans votre fichier .csproj en tant qu’enfant sur le noeud <project>.

Points clés:

Utilisez la commande Exec pour attrib +H Directory avant d'exécuter aspnet_compiler.exe via la tâche AspNetCompiler, puis attrib -H Directory par la suite.

Créez une ItemGroup pour aspirer tous les fichiers qui doivent encore être copiés.

Exécutez la tâche Copy en utilisant cette ItemGroup pour placer les fichiers là où ils doivent être afin que le reste de la tâche de publication puisse les inclure. Nous pouvons utiliser toutes les variables que Microsoft a créées lors de la création de cette tâche. Nous pouvons donc les utiliser ici également.

Pro pour modifier la tâche initiale: très peu de changements sur le comportement normal, donc ça devrait toujours fonctionner.

Possibilité de modifier la tâche d'origine: Microsoft pourrait modifier cette tâche ultérieurement, rendant notre copie obsolète.

Si vous n'avez pas mes exigences étranges, la solution la plus simple pour masquer un dossier est la suivante:

<Target Name="Test" BeforeTargets="AspNetPreCompile">
    <Exec Command="attrib +H Directory" />
</Target>
<Target Name="Test" AfterTargets="AspNetPreCompile">
    <Exec Command="attrib -H Directory" />
</Target>

Réponse inspirée par le commentaire de Twamley dans Arthur Nunes answer.

2
Adam Venezia

Ma solution à cette erreur a été une combinaison de deux réponses préexistantes sur cette page. J'avais un fichier .h dans mon répertoire de projet Web qui n'avait pas posé de problème jusqu'à ce que j'essaye de construire le projet sur une machine VS 2017.

Dans mon cas, je l'ai simplement compressé, mais le résultat semble être que vous ne pouvez plus conserver de fichiers de code non liés dans le répertoire Web, sinon VS trébuchera en essayant de les compiler.

0
Psiloc

Dans mon cas, le problème était que la configuration Web d'une solution parent (projet de niveau racine) dans IIS se trouvait dans sa configuration Web (par erreur, je ne savais pas comment cela avait abouti). Il a fallu beaucoup de temps pour localiser, car rien de ce que je pouvais faire dans ma solution/projet ne pouvait l’affecter de quelque manière que ce soit.

Donc, il pourrait être intéressant de consulter le web.config de tout ce qui pourrait être impliqué.

0
user230910

Dans mon cas, sur une nouvelle machine, j'ai installé VS2017 et ouvert une application Web asp.net core 1.1 à partir du contrôle de source. L'erreur est apparue. J'ai installé node.js et le projet compilé.

0
Armin K

Pour moi, cette erreur montrait que le chemin physique de mon site Web était invalide dans IIS. Pour résoudre ce problème, cliquez avec le bouton droit sur le site Web (Gérer le site Web -> Paramètres avancés -> Chemin physique). 

0
Mr. Blond
0
mtoregan