MSBuild远程Web部署中的App_Offline

Nic*_*ick 22 msbuild web-deployment msdeploy webdeploy

我在MSBuild脚本中有以下任务,使用Web Deploy(MSDeploy服务)部署到远程服务器:

  <Target Name="Deploy">
    <MSBuild
            Projects="$(SolutionFile)"
            Properties="Configuration=Release; DeployOnBuild=True; 
              DeployTarget=MsDeployPublish; MSDeployPublishMethod=WMSvc; 
              MsDeployServiceUrl=$(DeployServiceUrl); 
              DeployIisAppPath=$(DeployIisAppPath); 
              UserName=$(DeployUserName); Password=$(DeployPassword); 
              CreatePackageOnPublish=True; AllowUntrustedCertificate=True" />
  </Target>
Run Code Online (Sandbox Code Playgroud)

它工作正常.但是,我想在部署应用程序之前放置app_offline.htm文件(在远程服务器上),并在部署之后删除app_offline.htm文件(或出错时).是否有MSBuild属性或任何其他脚本调整才能实现?

提前致谢.

Say*_*imi 22

我最近在http://sedodream.com/2012/01/08/HowToTakeYourWebAppOfflineDuringPublishing.aspx上发表了关于此的博文.它比应该更难,我正在努力简化以后的版本.无论如何,我已经为您粘贴了所有内容.

我收到了一封客户电子邮件,询问他们如何在Visual Studio中发布发布的整个过程中使他们的Web应用程序/站点脱机.使您的站点脱机的一种简单方法是在站点根目录中删除app_offline.htm文件.有关这方面的更多信息,请阅读ScottGu的帖子,请参阅以下资源部分中的链接.不幸的是,Web Deploy本身并不支持这一点.如果您希望Web Deploy(也称为MSDeploy)本机支持此功能,请在http://aspnet.uservoice.com/forums/41199-general/suggestions/2499911-take-my-site-app-offline-during上投票- 出版.

由于Web Deploy不支持此功能,因此需要执行以下步骤:

  1. 发布app_offline.htm
  2. 发布应用程序,并确保app_offline.htm包含在要发布的有效内容中
  3. 删除app_offline.htm

1将在发布过程开始之前使应用程序脱机.

2将确保我们发布时不删除app_offline.htm(从而使应用程序保持脱机状态)

3将删除app_offline.htm并使网站重新联机

现在我们知道需要做什么,让我们来看看实现.首先是简单的部分.在名为app_offline-template.htm的Web应用程序项目(WAP)中创建一个文件.这将是最终成为目标服务器上的app_offline.htm文件的文件.如果您将其留空,您的用户将收到一条通用消息,指出应用程序处于脱机状态,但最好在该文件中放置静态HTML(无ASP.NET标记),以便用户知道该网站将返回以及您认为与您的用户相关的任何其他信息.添加此文件时,应在"属性"网格中将"构建操作"更改为"无".这将确保此文件本身未发布/打包.由于文件以.htm结尾,因此默认情况下将发布.见下图.

在此输入图像描述

现在是困难的部分.对于Web应用程序项目,我们在发布/包过程中有一个钩子,我们将其称为"wpp.targets".如果要扩展发布/包过程,可以在与项目文件本身相同的文件夹中创建名为{ProjectName} .wpp.targets的文件.这是我创建的文件,您可以将内容复制并粘贴到wpp.targets文件中.我将解释重要的部分,但希望发布整个文件供你说服.注意:您可以从我的github仓库获取此文件的最新版本,该链接位于下面的资源部分.

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="InitalizeAppOffline">
    <!-- 
    This property needs to be declared inside of target because this is imported before
    the MSDeployPath property is defined as well as others -->
    <PropertyGroup>
      <MSDeployExe Condition=" '$(MSDeployExe)'=='' ">$(MSDeployPath)msdeploy.exe</MSDeployExe>
    </PropertyGroup>    
  </Target>

  <PropertyGroup>
    <PublishAppOfflineToDest>
      InitalizeAppOffline;
    </PublishAppOfflineToDest>
  </PropertyGroup>

  <!--
    %msdeploy% 
      -verb:sync 
      -source:contentPath="C:\path\to\app_offline-template.htm" 
      -dest:contentPath="Default Web Site/AppOfflineDemo/app_offline.htm"
  -->

  <!--***********************************************************************
  Make sure app_offline-template.htm gets published as app_offline.htm
  ***************************************************************************-->
  <Target Name="PublishAppOfflineToDest" 
          BeforeTargets="MSDeployPublish" 
          DependsOnTargets="$(PublishAppOfflineToDest)">
    <ItemGroup>
      <_AoPubAppOfflineSourceProviderSetting Include="contentPath">
        <Path>$(MSBuildProjectDirectory)\app_offline-template.htm</Path>
        <EncryptPassword>$(DeployEncryptKey)</EncryptPassword>
        <WebServerAppHostConfigDirectory>$(_MSDeploySourceWebServerAppHostConfigDirectory)</WebServerAppHostConfigDirectory>
        <WebServerManifest>$(_MSDeploySourceWebServerManifest)</WebServerManifest>
        <WebServerDirectory>$(_MSDeploySourceWebServerDirectory)</WebServerDirectory>
      </_AoPubAppOfflineSourceProviderSetting>

      <_AoPubAppOfflineDestProviderSetting Include="contentPath">
        <Path>"$(DeployIisAppPath)/app_offline.htm"</Path>
        <ComputerName>$(_PublishMsDeployServiceUrl)</ComputerName>
        <UserName>$(UserName)</UserName>
        <Password>$(Password)</Password>
        <EncryptPassword>$(DeployEncryptKey)</EncryptPassword>
        <IncludeAcls>False</IncludeAcls>
        <AuthType>$(AuthType)</AuthType>
        <WebServerAppHostConfigDirectory>$(_MSDeployDestinationWebServerAppHostConfigDirectory)</WebServerAppHostConfigDirectory>
        <WebServerManifest>$(_MSDeployDestinationWebServerManifest)</WebServerManifest>
        <WebServerDirectory>$(_MSDeployDestinationWebServerDirectory)</WebServerDirectory>
      </_AoPubAppOfflineDestProviderSetting>
    </ItemGroup>

    <MSdeploy
          MSDeployVersionsToTry="$(_MSDeployVersionsToTry)"
          Verb="sync"
          Source="@(_AoPubAppOfflineSourceProviderSetting)"
          Destination="@(_AoPubAppOfflineDestProviderSetting)"
          EnableRule="DoNotDeleteRule"
          AllowUntrusted="$(AllowUntrustedCertificate)"
          RetryAttempts="$(RetryAttemptsForDeployment)"
          SimpleSetParameterItems="@(_AoArchivePublishSetParam)"
          ExePath="$(MSDeployPath)" />
  </Target>

  <!--***********************************************************************
  Make sure app_offline-template.htm gets published as app_offline.htm
  ***************************************************************************-->
  <!-- We need to create a replace rule for app_offline-template.htm->app_offline.htm for when the app get's published -->
  <ItemGroup>
    <!-- Make sure not to include this file if a package is being created, so condition this on publishing -->
    <FilesForPackagingFromProject Include="app_offline-template.htm" Condition=" '$(DeployTarget)'=='MSDeployPublish' ">
      <DestinationRelativePath>app_offline.htm</DestinationRelativePath>
    </FilesForPackagingFromProject>

    <!-- This will prevent app_offline-template.htm from being published -->
    <MsDeploySkipRules Include="SkipAppOfflineTemplate">
      <ObjectName>filePath</ObjectName>
      <AbsolutePath>app_offline-template.htm</AbsolutePath>
    </MsDeploySkipRules>
  </ItemGroup>

  <!--***********************************************************************
  When publish is completed we need to delete the app_offline.htm
  ***************************************************************************-->
  <Target Name="DeleteAppOffline" AfterTargets="MSDeployPublish">
    <!--
    %msdeploy% 
      -verb:delete 
      -dest:contentPath="{IIS-Path}/app_offline.htm",computerName="...",username="...",password="..."
    -->
    <Message Text="************************************************************************" />
    <Message Text="Calling MSDeploy to delete the app_offline.htm file" Importance="high" />
    <Message Text="************************************************************************" />

    <ItemGroup>
      <_AoDeleteAppOfflineDestProviderSetting Include="contentPath">
        <Path>$(DeployIisAppPath)/app_offline.htm</Path>
        <ComputerName>$(_PublishMsDeployServiceUrl)</ComputerName>
        <UserName>$(UserName)</UserName>
        <Password>$(Password)</Password>
        <EncryptPassword>$(DeployEncryptKey)</EncryptPassword>
        <AuthType>$(AuthType)</AuthType>
        <WebServerAppHostConfigDirectory>$(_MSDeployDestinationWebServerAppHostConfigDirectory)</WebServerAppHostConfigDirectory>
        <WebServerManifest>$(_MSDeployDestinationWebServerManifest)</WebServerManifest>
        <WebServerDirectory>$(_MSDeployDestinationWebServerDirectory)</WebServerDirectory>
      </_AoDeleteAppOfflineDestProviderSetting>
    </ItemGroup>

    <!-- 
    We cannot use the MSDeploy/VSMSDeploy tasks for delete so we have to call msdeploy.exe directly.
    When they support delete we can just pass in @(_AoDeleteAppOfflineDestProviderSetting) as the dest
    -->
    <PropertyGroup>
      <_Cmd>"$(MSDeployExe)" -verb:delete -dest:contentPath="%(_AoDeleteAppOfflineDestProviderSetting.Path)"</_Cmd>
      <_Cmd Condition=" '%(_AoDeleteAppOfflineDestProviderSetting.ComputerName)' != '' ">$(_Cmd),computerName="%(_AoDeleteAppOfflineDestProviderSetting.ComputerName)"</_Cmd>
      <_Cmd Condition=" '%(_AoDeleteAppOfflineDestProviderSetting.UserName)' != '' ">$(_Cmd),username="%(_AoDeleteAppOfflineDestProviderSetting.UserName)"</_Cmd>
      <_Cmd Condition=" '%(_AoDeleteAppOfflineDestProviderSetting.Password)' != ''">$(_Cmd),password=$(Password)</_Cmd>
      <_Cmd Condition=" '%(_AoDeleteAppOfflineDestProviderSetting.AuthType)' != ''">$(_Cmd),authType="%(_AoDeleteAppOfflineDestProviderSetting.AuthType)"</_Cmd>
    </PropertyGroup>

    <Exec Command="$(_Cmd)"/>
  </Target>  
</Project>
Run Code Online (Sandbox Code Playgroud)

1发布app_offline.htm

#1的实现包含在目标PublishAppOfflineToDest中.我们需要执行的msdeploy.exe命令是.

msdeploy.exe 
    -source:contentPath='C:\Data\Personal\My Repo\sayed-samples\AppOfflineDemo01\AppOfflineDemo01\app_offline-template.htm' 
    -dest:contentPath='"Default Web Site/AppOfflineDemo/app_offline.htm"',UserName='sayedha',Password='password-here',ComputerName='computername-here',IncludeAcls='False',AuthType='NTLM' -verb:sync -enableRule:DoNotDeleteRule
Run Code Online (Sandbox Code Playgroud)

为此,我将利用MSDeploy任务.在PublishAppOfflineToDest目标内部,您可以通过为源和目标创建项目来了解如何实现此目标.

2发布应用程序,并确保app_offline.htm包含在要发布的有效内容中

这部分是由片段完成的

<!--***********************************************************************
Make sure app_offline-template.htm gets published as app_offline.htm
***************************************************************************-->
<!-- We need to create a replace rule for app_offline-template.htm->app_offline.htm for when the app get's published -->
<ItemGroup>
  <!-- Make sure not to include this file if a package is being created, so condition this on publishing -->
  <FilesForPackagingFromProject Include="app_offline-template.htm" Condition=" '$(DeployTarget)'=='MSDeployPublish' ">
    <DestinationRelativePath>app_offline.htm</DestinationRelativePath>
  </FilesForPackagingFromProject>

  <!-- This will prevent app_offline-template.htm from being published -->
  <MsDeploySkipRules Include="SkipAppOfflineTemplate">
    <ObjectName>filePath</ObjectName>
    <AbsolutePath>app_offline-template.htm</AbsolutePath>
  </MsDeploySkipRules>
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

FilesForPackagingFromProject的项值将在您处理发布的文件夹中将app_offline-template.htm转换为app_offline.htm.此外还有一个条件,以便它只发生在发布而不是包装.我们不希望app_offline-template.htm在包中(但如果它也是如此,它不是世界末日).

MsDeploySkiprules的元素将确保app_offline-template.htm本身不会发布.这可能不是必需的,但不应该受到伤害.

3删除app_offline.htm

现在我们的应用程序已发布,我们需要从dest web应用程序中删除app_offline.htm文件.msdeploy.exe命令是:

%msdeploy%-verb:delete -dest:contentPath ="{IIS-Path} /app_offline.htm",computerName ="...",username ="...",password ="..."

这是在DeleteAppOffline目标内部实现的.这个目标将在发布后自动执行,因为我已经包含了属性AfterTargets ="MSDeployPublish".在该目标中,您可以看到我正在直接构建msdeploy.exe命令,看起来MSDeploy任务不支持删除动词.

如果您尝试这样做,请告诉我您是否遇到任何问题.我正在考虑从中创建一个Nuget包,以便您可以安装该包.这需要一些工作,所以如果你对此感兴趣,请告诉我.

资源

  1. 我的AppOffline wpp.targets文件的最新版本
  2. ScottGu在app_offline.htm上的博客

  • msbuild.exe现在有一个名为-enableRule:AppOffline的参数,可在发布站点之前使应用程序脱机.有没有办法从msbuild调用它? (3认同)
  • @SergeyZwezdin WebDeploy v 3.0(在服务器上)确实有这个选项.请参阅http://www.iis.net/learn/publish/deploying-application-packages/taking-an-application-offline-before-publishing.它目前不支持自定义脱机文件. (3认同)

Ros*_*sim 13

现在,WebDeploy v3.0支持此功能.您只需将此行添加到"Properties\PublishProfiles"中的发布配置文件中

<EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>
Run Code Online (Sandbox Code Playgroud)

因此,生成的发布配置文件将如下所示.

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>
    <WebPublishMethod>MSDeploy</WebPublishMethod>
    <MSDeployServiceURL>(removed)</MSDeployServiceURL>
    <DeployIisAppPath>Default Web Site</DeployIisAppPath>
    <AllowUntrustedCertificate>True</AllowUntrustedCertificate>
    <SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
    <DeployAsIisApp>False</DeployAsIisApp>
    <MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
    <UserName>sayedha</UserName>
    <ExcludeApp_Data>False</ExcludeApp_Data>
    <_SavePWD>True</_SavePWD>
  </PropertyGroup>
</Project>
Run Code Online (Sandbox Code Playgroud)

我已对此进行了测试,并且在部署期间确实使我的应用程序脱机,但遗憾的是我仍偶尔会出现'PrecompiledApp.config is used'错误.

有关这方面的更多信息,请访问:http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksum.aspx