发布网站时出现aspnet_compiler null reference exception错误

5
我在通过命令行发布解决方案时遇到了问题。在各个项目中,它会间歇性地失败,但偶尔会成功。我既遇到了空引用错误,也遇到了“运行线程的应用程序域已被卸载”的错误,这可能只是带有竞争条件的空引用。它似乎只会在具有 Web 服务(原始 .asmx 和带有 .svc 或无文件激活的 WCF)的项目上失败。它有时成功的事实使我认为这不是我们代码的问题,尽管可能有一些更改可以减轻潜在原因(无论是什么)。

我尝试/检查的内容:

  • 我运行了 tfpt scorch 来清理任何本地更改,包括构建输出,但没有成功,所以我知道这不是源目录的问题。
  • 我清除了位于 C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files(我们使用的是 32 位)的临时文件,似乎进展更多了,但仍然存在问题。在另一次发布后,目录仍然为空,所以可能与此无关。
  • 通过 Process Monitor,我发现 aspnet_compiler 正在写入到 %LocalAppData%\Temp\Temporary ASP.NET Files。清除这些文件有时似乎有效,或者可能只是我运气好,但然后它又开始失败了。我没有发现其他可能相关的内容。
  • 确保我有足够的 RAM,似乎没有什么区别。
  • 单线程运行 msbuild,没有区别
  • 从命令行运行 aspnet_compiler(从 MSBuild 日志输出中获取命令),总是成功的
  • 没有压缩的文件夹
  • 我使用的是最新稳定版的 Visual Studio(VS 2013 更新 2),但这不应该有影响,因为我是从命令行运行的,使用的可执行文件在框架目录中。
  • 一些失败的项目中没有 App_Code 文件夹

构建输出没有提供任何有用的信息,所以我设置了 DebugDiag 来在崩溃时输出。以下是结果:

DetailID = 1
    Count:    1
    Type:     System.NullReferenceException
    Message:  
    Stack:    
        System.Web.Compilation.DiskBuildResultCache.CacheBuildResult(System.String, System.Web.Compilation.BuildResult, Int64, System.DateTime)
        System.Web.Compilation.BuildManager.CacheBuildResultInternal(System.String, System.Web.Compilation.BuildResult, Int64, System.DateTime)
        System.Web.Compilation.WebDirectoryBatchCompiler.CacheAssemblyResults(System.Web.Compilation.AssemblyBuilder, System.CodeDom.Compiler.CompilerResults)
        System.Web.Compilation.WebDirectoryBatchCompiler.CompileAssemblyBuilder(System.Web.Compilation.AssemblyBuilder)
        System.Web.Compilation.WebDirectoryBatchCompiler.CompileAssemblyBuilderParallel(System.Collections.ICollection)
        System.Web.Compilation.WebDirectoryBatchCompiler.CompileNonDependentBuildProviders(System.Collections.ICollection)
        System.Web.Compilation.WebDirectoryBatchCompiler.Process()
        System.Web.Compilation.BuildManager.BatchCompileWebDirectoryInternal(System.Web.Hosting.VirtualDirectory, Boolean)
        System.Web.Compilation.BuildManager.BatchCompileWebDirectory(System.Web.Hosting.VirtualDirectory, System.Web.VirtualPath, Boolean)
        System.Web.Compilation.BuildManager.PrecompileWebDirectoriesRecursive(System.Web.Hosting.VirtualDirectory, Boolean)
        System.Web.Compilation.BuildManager.PrecompileAppInternal(System.Web.VirtualPath, System.Collections.Generic.IEnumerable`1<System.String>)
        System.Web.Compilation.BuildManager.PrecompileApp(System.Web.VirtualPath, System.Collections.Generic.IEnumerable`1<System.String>)
        System.Web.Compilation.BuildManager.PrecompileApp(System.Web.Compilation.ClientBuildManagerCallback, System.Collections.Generic.IEnumerable`1<System.String>)
        System.Web.Compilation.BuildManagerHost.PrecompileApp(System.Web.Compilation.ClientBuildManagerCallback, System.Collections.Generic.List`1<System.String>)
        [GCFrame]
        [GCFrame]
        [ContextTransitionFrame]
        [GCFrame]
        [GCFrame]
        [GCSafeCollectionFrame]
        [GCSafeCollectionFrame]
        [GCSafeCollectionFrame]
        [GCSafeCollectionFrame]
        [GCSafeCollectionFrame]
        [GCSafeCollectionFrame]
        [GCSafeCollectionFrame]
        [TPMethodFrame]
        *** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v4.0.30319_32\System.Web\3d247ccfb800c38a29cf91c27a6339da\System.Web.ni.dll
        Module load completed but symbols could not be loaded for C:\Windows\assembly\NativeImages_v4.0.30319_32\System.Web\3d247ccfb800c38a29cf91c27a6339da\System.Web.ni.dll
        System.Web.Compilation.ClientBuildManager.PrecompileApplication(System.Web.Compilation.ClientBuildManagerCallback)
        *** ERROR: Module load completed but symbols could not be loaded for C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe
        [GCFrame]


DetailID = 2
    Count:    1
    Type:     System.NullReferenceException
    Message:  Object reference not set to an instance of an object.
    Stack:    
        [GCFrame]
        [GCFrame]
        [GCFrame]
        [GCSafeCollectionFrame]
        [GCSafeCollectionFrame]
        [GCSafeCollectionFrame]
        [GCSafeCollectionFrame]
        [GCSafeCollectionFrame]
        [GCSafeCollectionFrame]
        [GCSafeCollectionFrame]
        [TPMethodFrame]
        System.Web.Compilation.ClientBuildManager.PrecompileApplication(System.Web.Compilation.ClientBuildManagerCallback, Boolean)
        System.Web.Compilation.ClientBuildManager.PrecompileApplication(System.Web.Compilation.ClientBuildManagerCallback)
        System.Web.Compilation.Precompiler.Main(System.String[])
        [GCFrame]

我发现其他人也遇到了类似的问题,但是他们要么没有得到答案,要么提供的解决方案对我无效。还有其他的想法吗? 编辑: 这是我正在使用的命令行:
"C:\Program Files (x86)\MSBuild\12.0\bin\MSBuild.exe" Solution.sln /t:Build /m:1 /p:Configuration=Prod /p:Platform="Mixed Platforms" /p:DeployOnBuild=true /p:PublishProfile=Prod /p:AutoParameterizationWebConfigConnectionStrings=false /v:diag > out.txt

这是一些控制台输出(已重定向到文件)的内容:
Target "AspNetPreCompile: (TargetId:3773)" in file "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Transform\Microsoft.Web.Publishing.AspNetCompileMerge.targets" from project "C:\Source\Project\Project.csproj" (target "PipelineAspNetCompileMergePhase" depends on it):
Task "AspNetCompiler" (TaskId:2474)
  Task Parameter:PhysicalPath=C:\Source\Project\obj\x86\Release\AspnetCompileMerge\Source (TaskId:2474)
  Task Parameter:TargetPath=C:\Source\Project\obj\x86\Release\AspnetCompileMerge\TempBuildDir (TaskId:2474)
  Task Parameter:VirtualPath=/ (TaskId:2474)
  Task Parameter:Debug=False (TaskId:2474)
  Task Parameter:Updateable=False (TaskId:2474)
  Task Parameter:ToolPath=C:\Windows\Microsoft.NET\Framework\v4.0.30319 (TaskId:2474)

  C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe -v / -p C:\Source\Project\obj\x86\Release\AspnetCompileMerge\Source C:\Source\Project\obj\x86\Release\AspnetCompileMerge\TempBuildDir  (TaskId:2474)
  Microsoft (R) ASP.NET Compilation Tool version 4.0.30319.34209 (TaskId:2474)
  Utility to precompile an ASP.NET application (TaskId:2474)
  Copyright (C) Microsoft Corporation. All rights reserved. (TaskId:2474)
   (TaskId:2474)
ASPNETCOMPILER : error ASPRUNTIME: Object reference not set to an instance of an object. [C:\Source\Project\Project.csproj]
  The command exited with code 1. (TaskId:2474)

Done executing task "AspNetCompiler" -- FAILED. (TaskId:2474)
Done building target "AspNetPreCompile" in project "Project.csproj" -- FAILED.: (TargetId:3773)

正如您所见,msbuild诊断输出并不是很有用。

编辑2: 尝试调试aspnet_compiler以更好地解决问题。我启动了gflags.exe以启用自动附加到调试器。我能够在NullReferenceException上中断,但我无法加载System.Web的符号。它来自C:\Windows\Microsoft.Net\assembly\GAC_32\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll。

根据堆栈跟踪,它在这个方法中失败:

internal override void CacheBuildResult(string cacheKey, BuildResult result, long hashCode, DateTime utcStart)
{
  if (!result.CacheToDisk)
    return;
  if (HostingEnvironment.ShutdownInitiated)
  {
    BuildResultCompiledAssemblyBase compiledAssemblyBase = result as BuildResultCompiledAssemblyBase;
    if (compiledAssemblyBase == null)
      return;
    this.MarkAssemblyAndRelatedFilesForDeletion(compiledAssemblyBase.ResultAssembly.GetName().Name);
  }
  else
    new PreservationFileWriter(this.PrecompilationMode).SaveBuildResultToFile(this.GetPreservedDataFileName(cacheKey), result, hashCode);
}

任何一个变量都可能为null,导致异常:result、HostingEnvironment和compiledAssemblyBase。

分享一下如何从命令行启动并包含所有参数。此外,创建一个诊断日志以获得更多的构建输出,并引用日志而不是控制台输出以获取详细信息。 - Nicodemeus
@Nicodemeus:我编辑了我的问题,以包含更多细节。关于诊断日志,我想你指的是 /v:diag - Nelson Rothermel
3个回答

2

你可能有所发现。我的旧电脑和出现问题的新电脑都安装了 McAfee 杀毒软件。由于现在不再出现问题,也许某些设置已经不同了,但至少我们有共同点。 - Nelson Rothermel
对我来说,只需排除以下两个文件夹即可: C:\Users\<user>\AppData\Local\Temp\Temporary ASP.NET FilesC:\Windows\Microsoft.NET\Framework\ (我想你可以进一步缩小范围) 以免 McAfee 扫描这些文件夹。 - Albin Sunnanbo

1
移除-u选项应该可以解决问题,因为这对我有效。

我相当确定我尝试过可更新和不可更新的两种方式。从我的问题来看,日志显示了“任务参数:Updateable=False(TaskId:2474)”。大约两周后,我会回到这个项目上,并且现在我有一台不同的电脑,所以那时应该会有一些更新。 - Nelson Rothermel
我已经验证它们没有被标记为可更新,所以这不适用于我的情况。 - Nelson Rothermel

1
如果我要解决这个问题,我会尽可能地将其隔离,以下是计划。
我看到以下可能的原因:
1.构建环境 2.构建过程 3.编译器错误 4.源代码/项目结构太复杂
在大多数像你这样的复杂情况中,所有因素都起作用,因此逐个孤立原因可能有所帮助,或者至少可能显示更容易修复和继续进行的其他/新错误。
构建环境
您可以尝试在其他计算机或其他计算机上构建同一项目(构建指解决任务-从命令行发布网站)。如果您遇到相同的问题,则没有显示任何内容,但如果其他环境正常(或至少其中之一)-则肯定存在环境问题。
它可以是任何东西-.Net版本和/或修复程序,操作系统版本,用于命令行使用不正确的框架的路径变量,本地项目路径中的空格-无论如何,但如果您可以使其在其他计算机上正常工作,则将知道您需要查看构建过程而不是其他内容。
你可以尝试构建任何示例项目,以确保你可以发布简单的项目。
构建过程
看起来你已经确定问题在于发布步骤,但是你可以尝试一下 - 只编译而不发布,或者在现有二进制文件/发布文件夹上运行发布目标等 - 你需要尝试隔离特定的步骤(如果有),排除对其他构建步骤的依赖。
最有可能这并没有什么帮助,因为我预计整个过程都会失败 - 但谁知道呢。
编译器错误
这个问题与下一个问题密切相关。如果可能的话,你可以尝试使用VS2012而不是VS2013进行构建。
源代码/项目结构过于复杂
在解决方案中预先构建所有项目,并使用对结果DLL的引用,而不是对项目的引用。如果一切正常 - 逐个返回项目源代码,以便你至少可以了解哪个项目导致编译器失败。
当/如果你隔离出一个项目后,你可以尝试将其部分编译为单独的DLL,在某些情况下,你可能会意识到某些特定的代码结构/标记应该被重写以满足编译器。

如果问题出现在 Web 项目或其他类型的项目中,无法将其编译为单个 DLL,则可以尝试“关闭”项目的整个部分 - 例如,排除包含 Web 页面的多个文件夹并检查结果。

希望这有所帮助,但肯定需要大量努力才能隔离问题;但在大多数情况下,隔离特定问题解决了问题的重要部分。


被拖到另一个项目,但很快会回来继续。我有一个简单的项目,但解决方案很复杂。我将尝试进一步简化,并查看是否可以缩小到特定文件、引用等。我还没有尝试在另一台机器上构建,但这绝对是个好主意。不发布构建可以正常工作。事实上,没有预编译的发布也可以工作。一旦我有更多时间回来处理这个问题,我会分而治之。如果你的任何建议有所帮助,我会给你积分。 - Nelson Rothermel
好的,看起来新电脑解决了问题。我再也没有使用相同配置时出现这些错误了。这是你之前提到的我没有尝试过的其中一件事情,所以你终于得到了赏金。 :) - Nelson Rothermel
很高兴听到它有所帮助。 - Lanorkin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接