无法将预编译的合并Web应用程序部署到Azure

3
我正在尝试将一个混合了Web Forms、MVC和WebAPI的ASP.NET Web应用程序部署到Azure。由于有大量的aspx/ascx文件,所以它们确实需要预编译,否则每次部署都会导致网站运行缓慢一段时间。
我正在尝试通过GitHub和kudu进行SCM集成部署,使用预编译视图,并将所有内容合并到一个单独的程序集中。
请注意:
  • 禁用预编译后,部署可以正常工作。
  • 从Visual Studio进行部署也可以正常工作。
  • 如果我从Azure日志中复制msbuild命令,替换相关路径,并在我的Windows 8.1机器上本地运行,构建也可以正常工作。
我已经设置了高级预编译设置如下:
  • 不允许预编译站点可更新
  • 不发出调试信息
  • 将所有页面和控件输出合并到一个单独的程序集中=AppViews.dll
这是Azure的.deployment文件:
[config]
project = WebSite/WebSite.csproj
SCM_BUILD_ARGS=/p:Configuration=Release;PublishProfile=azure-prod /v:n

你注意到我正在发送冗长性/v以获得额外的诊断信息。
以下是部署日志末尾提供的信息:
AspNetPreCompile:
  D:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe -v \ -p D:\home\site\repository\WebSite\obj\Release\AspnetCompileMerge\Source -c D:\home\site\repository\WebSite\obj\Release\AspnetCompileMerge\TempBuildDir 
GenerateAssemblyInfoFromExistingAssembleInfo:
  Creating directory "obj\Release\AssemblyInfo".
  D:\Windows\Microsoft.NET\Framework\v4.0.30319\Csc.exe /out:obj\Release\AssemblyInfo\AssemblyInfo.dll /target:library Properties\AssemblyInfo.cs
AspNetMerge:
  Running aspnet_merge.exe.
  D:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\aspnet_merge.exe D:\home\site\repository\WebSite\obj\Release\AspnetCompileMerge\TempBuildDir -w AppViews.dll -copyattrs obj\Release\AssemblyInfo\AssemblyInfo.dll -a  
aspnet_merge : error 1003: The directory 'D:\home\site\repository\WebSite\obj\Release\AspnetCompileMerge\TempBuildDir' does not exist. [D:\home\site\repository\WebSite\WebSite.csproj]
Done Building Project "D:\home\site\repository\WebSite\WebSite.csproj" (Build;pipelinePreDeployCopyAllFilesToOneFolder target(s)) -- FAILED.

Build FAILED.

似乎aspnet_compiler.exe正在运行,但并没有按照它应该做的来,这也就是为什么TempBuildDir目录(预期为编译器的输出)在AspNetMerge目标执行之前不存在的原因。与我的系统相比,那个目录确实存在,包含着aspx/ascx等标记文件、静态内容、PrecompiledApp.config文件以及bin目录中的一大堆东西。
aspnet_compiler.exe有一个-errorstack标志,但我不清楚如何让MSBuild通过.deployment文件添加这个标志,甚至不确定该应用程序是否真的会抛出错误。
我可以通过Visual Studio进行部署,但我希望利用SCM集成,这样我只需要将代码推送到生产分支即可。有什么建议吗?

Azure网站上的aspnet_compiler已被替换为存根exe。您可能希望在此处提出问题 - https://github.com/projectkudu/kudu - 以供部署团队跟踪并找出解决方案。 - Pranav
@Pranav,你有这个存根exe的任何文档吗?我从Kudu Services URL(sitename.scm.azurewebsites.net)下载了exe,并使用dotTrace进行检查,看起来基本上是相同的东西。我甚至尝试将我的本地副本添加到我的存储库中,并使用自定义MSBuild目标更改路径以使用我的副本,但无济于事。 - David Boike
2个回答

3

我在https://github.com/projectkudu/kudu/issues/1341上回复过,但是为了让其他人也能看到我的回答,我将其复制到这里。

很久以前,我们发现由于aspnet_compiler.exe处理配置文件夹的方式,它在Azure网站中无法正常工作。那时我们进行了一些修改,有点像黑客技术,但是它让我们继续前进:我们将其变成了一个空操作,通过将HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\aspnet_compiler.exe指向我们自己的虚拟exe (D:\Program Files (x86)\aspnet_compiler\KuduAspNetCompiler.exe)。

但是现在看起来它似乎已经正常工作了,可能是由于Azure网站托管环境的改进。所以我们会尝试摆脱这个hack,并进行全面的测试以确保它不会导致任何重大的退步。如果一切顺利,我们可以将其投入生产,从而实现这些场景。

在短期内,您可以通过以下方式解决此问题:

  • 将aspnet_compiler.exe从D:\Windows\Microsoft.NET\Framework\v4.0.30319复制到您自己的站点文件中,但使用不同的名称(例如aspnet_compiler2.exe)
  • 说服msbuild使用该exe

1

注意:此GitHub问题关于projectkudu最终将使此解决方案过时,但目前该问题已被归档为积压问题,因此此解决方案仍然有效。

非常感谢David Ebbo。有了这些信息,我能够暂时启动我的构建。

首先,我使用可用于https://{WEBSITE_NAME}.scm.azurewebsites.net/DebugConsole的诊断控制台从Azure实例中下载了aspnet_compiler.exe,并将其添加到自己的存储库中。这样就不会有任何32/64位等之间的区别问题。我在我的存储库中将其重命名为azure_aspnet_compiler.exe

其次,AspNetCompiler任务没有提供更改工具名称的选项。它是硬编码的,但作为虚拟属性,因此可以覆盖。因此,我必须创建自己的任务类,并将其打包到自己的程序集中,我以发布模式构建了该程序集,并将其包含在我的存储库中。

public class AzureAspNetCompiler : Microsoft.Build.Tasks.AspNetCompiler
{
    private string _toolName = "aspnet_compiler.exe";

    protected override string ToolName
    {
        get { return _toolName; }
    }

    public string CustomToolName // Because ToolName cannot have a setter
    {
        get { return _toolName; }
        set { _toolName = value; }
    }
}

下一步,我需要替换MSBuild中的AspNetPreCompile任务,但我无法直接实现。但是那个任务本来就没有做任何事情,为什么不直接在它之后运行呢?
我在Website.csproj文件的顶部添加了这个代码,以导入包含AzureAspNetCompiler类的DLL。请注意,路径是相对于我正在编辑的Website.csproj文件的。
<UsingTask TaskName="AzureBuildTargets.AzureAspNetCompiler"
           AssemblyFile="..\DeploymentTools\AzureBuildTargets.dll" />

然后我在其下方添加了以下内容,基本上是从 C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web\Transform\Microsoft.Web.Publishing.AspNetCompileMerge.targets 中窃取 AspNetPreCompile 的 MSBuild 目标定义,并省略了顶部的一些属性设置内容(因为原始任务会为我们完成)。只需注意底部的 ToolPathCustomToolName 值即可(重命名后的)AzureAspNetCompiler 元素。
<PropertyGroup>
        <!--Relative to solution root apparently-->
        <LocalRepoDeploymentTools>.\DeploymentTools</LocalRepoDeploymentTools>
        <AzureAspnetCompilerPath>$([System.IO.Path]::GetFullPath($(LocalRepoDeploymentTools)))</AzureAspnetCompilerPath>
</PropertyGroup>

<Target Name="NoReallyAspNetPreCompile" AfterTargets="AspNetPreCompile">

<AzureAspNetCompiler
  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="$(AzureAspnetCompilerPath)"
  CustomToolName="azure_aspnet_compiler.exe"
    />

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

有了这个,一切都按照我的预期工作。

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