2013-12-12 206 views
11

我建立Web应用程序时/包装在构建服务器的Web应用程序“的CodeDOM提供类型Microsoft.VisualC.CppCodeProvider找不到”例外,它失败,出现以下异常:建设构建服务器

ASPNETCOMPILER错误ASPCONFIG:CodeDOM的提供者类型 “Microsoft.VisualC.CppCodeProvider,CppCodeProvider,版本= 10.0.0.0, 文化=中性公钥= b03f5f7f11d50a3a” 不能 定位。

构建服务器:

  • 的Windows Server 2008 R2标准
  • 的TeamCity 8.0.4
  • .NET 4.5
  • Windows SDK的Windows 7和.NET 4
  • 的Windows适用于Windows 8和.NET 4.5的SDK
  • 便携式类库工具
  • ASP MVC 4

该应用程序是一个ASP MVC 4网络应用程序,面向.NET 4.5。

构建配置包括使用MSBuild构建解决方案,使其能够部署到包中,以便稍后发布。

通过TeamCity的日志,我可以看到MSBuild运行“aspnet_compiler.exe”时出现错误。

在我的开发机器上没有问题的版本,也可以发布到本地IIS没有问题。

是否有人知道可能导致该问题的原因?

UPDATE

See my answer below.

回答

13

This post给了我一条重要线索:显然ASP.NET预编译扫描项目和输出文件,并尝试编译它发现自己的方式每个源文件,尽管它的语言(见here)。

在这种情况下,我的web应用程序依赖于一个项目,其中包括一个非托管dll沿“.h”文件。这些文件被复制到输出目录(“如果更新”则复制),这样我就可以在运行时对其进行拼写。

似乎ASP.NET预编译发现“.h”,并试图编译它,即使没有必要。而且,正如我所看到的那样,它失败了,因为我的构建服务器没有用于该作业的工具(它看起来像CppCodeProvider.NET 2.0 SDK一起提供)。

当我更改项目不将这些文件复制到输出目录时,构建运行良好。我还测试了复制文件,但在发布配置文件中将“PrecompileBeforePublish”设置为false,并且它也起作用。

现在我有一些选择,但我不喜欢任何人:

  • 禁用 “PrecompileBeforePublish”。我认为这样做的主要缺点是应用程序用户体验在第一次访问网站时会变慢。

  • 尝试从输出文件夹中排除文件,并在预编译之后再次添加它们。对于我不应该担心的事情来说,这似乎有很多工作要做。

  • 尝试告诉“aspnet_compiler.exe”执行时排除有问题的文件/文件夹。我不知道如何使用发布配置文件,因为我只能控制“PrecompileBeforePublish”。此外,似乎“aspnet_compiler.exe”不提供该选项(herehere)。

我认为现在我会禁用“PrecompileBeforePublish”,因为它似乎是一条很快的道路,几乎没有提示。但我相信应该有更好的方式来处理它,不包括使用发布配置文件进行预编译的文件夹或文件类型。

+0

我的天啊! - 非常感谢你这篇文章 - 你可能救了我几天的挫折,因为这正是我们发生的事情。你有没有找到一种方法来忽略文件夹? (尽管我的第一选择是从回购中删除违规文件。) – Edward

+0

不,爱德华,我必须保持“预编译前发布”禁用。然而,在这个问题发生后不久我就停止了关于这个项目的工作,所以也许答案仍然在某处=] –

+3

@爱德华我也遇到了这个问题。到目前为止,我运行aspnet_compiler.exe之前,在我的构建脚本中使用hidden属性('attrib + H c:\ path \ to \ problem \ directory')标记了我的没有编译必需的文件夹,然后重置隐藏的属性当它完成。 – twamley

0

在我的情况下,问题是IIS中父解决方案(根级项目)的Web配置在它的Web配置中有这个(错误地,不知道它是如何到达的)。花了很长时间才找到,因为我的解决方案/项目中无法做到的任何事情都会以任何方式影响它。

所以可能值得检查所有可能涉及的web.config。

0

对我来说,这个错误显示当我的网站的物理路径在IIS中无效。要解决这个问题,请点击网站(管理网站 - >高级设置 - >物理路径)。

17

对于我来说,这个错误在构建Web项目时在VS2017中弹出。修复的方法是在文件资源管理器中隐藏node_modules目录。显然这会阻止ASP.NET编译器扫描所有这些文件,从而防止出现错误。

+0

在VS 2017中工作 – ihimv

+0

这绝对是一个解决方法(我无法使用,因为隐藏了node_module文件夹打破了其他工作流程)。我发现安装.NET 3.5使这个问题消失了。 –

2

当我更新到VS2017时,开始发生这种情况。对我来说,问题是node.js,如果我删除了node_modules文件夹,那么该项目将无错误地生成。事实证明,在anders here建议的csproj文件中将MvcBuildViews的值更改为false可以修复它。这并不理想,因为在IIS渲染它们之前不会编译mvc视图。就个人而言,我只是隐藏node_modules文件夹来解决问题,但我想添加这个答案,以防止其他人解决根本问题。

<MvcBuildViews>false</MvcBuildViews>

0

我的方案,我需要装运Perl解释器与我的ASP.Net网站(不要问我为什么需要Perl和我很抱歉,我提前做的!),那包含导致aspnet_compiler.exe出错的.c文件,正如其他人提到的那样是他们的问题。 perl目录位于我的bin文件夹中,并且在运行时是必需的。

我发现的麻烦是当你attrib +H该文件夹,它确实被aspnet_compiler跳过,但是不会在我的发布输出文件夹中。所以我不得不通过隐藏文件夹,编译视图,取消隐藏文件夹,然后将文件夹复制到正确的位置来进一步破解它。这涉及修改原始的AspNetPreCompile任务。请看下图:

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

不修改原文件.targets,作为一个孩子复制到您的.csproj文件,这给<project>节点。

关键要点:

使用Exec命令attrib +H Directory通过AspNetCompiler任务运行aspnet_compiler.exe之前和之后attrib -H Directory

创建一个ItemGroup吸收所有仍需要复制的文件。

运行Copy任务,利用ItemGroup将文件放在需要的位置,以便发布任务的其余部分包含它们。我们可以使用Microsoft在创作此任务时所做的所有变量,因此我们也可以在这里使用这些变量。

修改原始任务的专业版:对正常行为的改动非常小,所以它应该仍然可以正常工作。

可能会修改原始任务:Microsoft可能会在将来更改此任务,使我们的副本过期。

如果没有我奇怪的要求,简单的解决方案,以隐藏的文件夹如下:

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

答案由亚瑟·努涅斯答案提出的意见twamley启发。

0

就我而言,在一台新机器上安装了VS2017,并从源代码管理中打开了一个asp.net core 1.1 web应用程序。错误出现了。我安装了node.js并编译了项目。