我的 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>
它工作正常。但是,我想在部署应用程序之前放置一个 app_offline.htm 文件(在远程服务器上),并在部署后(或出错时)删除 app_offline.htm 文件。是否有 MSBuild 属性或任何其他脚本调整来实现它?
提前致谢。
最佳答案
我最近在 http://sedodream.com/2012/01/08/HowToTakeYourWebAppOfflineDuringPublishing.aspx 上写了一篇关于这个的博客。 .这比它应该的要困难得多,我正在努力为以后的版本简化它。无论如何,我已经为您粘贴了所有内容。
我收到了一封客户电子邮件,询问他们如何在从 Visual Studio 进行发布的整个期间使他们的 Web 应用程序/站点脱机。使站点脱机的一种简单方法是在站点根目录中放置一个 app_offline.htm 文件。有关更多信息,您可以阅读 ScottGu 的帖子,链接在下面的资源部分。不幸的是,Web Deploy 本身不支持这个。如果您希望 Web Deploy(又名 MSDeploy) native 支持此功能,请在 http://aspnet.uservoice.com/forums/41199-general/suggestions/2499911-take-my-site-app-offline-during-publishing 上投票。 .
由于 Web Deploy 不支持此功能,因此难度会更大一些,并且需要我们执行以下步骤:
1 将在发布过程开始之前使应用脱机。
2 将确保当我们发布 app_offline.htm 时不会被删除(因此保持应用程序离线)
3 将删除 app_offline.htm 并使网站重新联机
现在我们知道需要做什么,让我们看看实现。首先是简单的部分。在您的 Web 应用程序项目 (WAP) 中创建一个名为 app_offline-template.htm 的文件。这将是最终成为目标服务器上的 app_offline.htm 文件的文件。如果您将其留空,您的用户将收到一条通用消息,说明该应用程序处于离线状态,但您最好放置 静态 HTML (无 ASP.NET 标记)在该文件中,让用户知道该站点将恢复,以及您认为与您的用户相关的任何其他信息。添加此文件时,您应该将“属性”网格中的“构建操作”更改为“无”。这将确保此文件本身未被发布/打包。由于文件以 .htm 结尾,因此默认情况下它将被发布。见下图。
现在是困难的部分。对于 Web 应用程序项目,我们有一个 Hook 到我们称为“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>
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
为了做到这一点,我将利用 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>
此处 FilesForPackagingFromProject 的项目值会将您的 app_offline-template.htm 转换为将处理发布的文件夹中的 app_offline.htm。还有一个条件,它只在发布期间发生,而不是在打包期间发生。我们不希望 app_offline-template.htm 出现在包中(但如果有的话也不是世界末日)。
MsDeploySkiprules 的元素将确保 app_offline-template.htm 本身不会被发布。这可能不是必需的,但它不应该受到伤害。
3 删除 app_offline.htm
现在我们的应用程序已经发布,我们需要从目标 Web 应用程序中删除 app_offline.htm 文件。 msdeploy.exe 命令将是:
%msdeploy%
-动词:删除
-dest:contentPath="{IIS-Path}/app_offline.htm",computerName="...",username="...",password="..."
这是在 DeleteAppOffline 目标内部实现的。该目标将在发布后自动执行,因为我已包含属性 AfterTargets=”MSDeployPublish”。在该目标中,您可以看到我正在直接构建 msdeploy.exe 命令,看起来 MSDeploy 任务不支持删除动词。
如果您尝试这样做,请让我知道您是否遇到任何问题。我正在考虑从中创建一个 Nuget 包,以便您可以安装该包。这需要一些工作,所以如果您对此感兴趣,请告诉我。
资源
关于msbuild - MSBuild 远程 Web 部署中的 App_Offline,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9059109/