<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属性或任何其他脚本调整来实现?
提前致谢。
解决方法
我收到了一封客户电子邮件,询问他们如何在Visual Studio中发布发布的整个时间内将他们的网络应用程序/网站脱机。将网站脱机的简单方法是将site_offline.htm文件放在site根目录下。有关更多信息,您可以阅读ScottGu的文章,请在下面的资源部分链接。不幸的是Web部署本身不支持这一点。如果您希望Web Deploy(又名MSDeploy)本地支持此功能,请在http://aspnet.uservoice.com/forums/41199-general/suggestions/2499911-take-my-site-app-offline-during-publishing投票。
由于Web Deploy不支持这一点,这将会更加困难,因此需要我们执行以下步骤:
>发布app_offline.htm
>发布应用程序,并确保app_offline.htm包含在正在发布的有效载荷内
>删除app_offline.htm
1将在发布流程开始之前使应用程序脱机。
2将确保当我们发布该app_offline.htm不被删除(并因此使应用程序脱机)
3将删除app_offline.htm并将网站重新联机
现在我们知道需要做什么让我们来看看实现。首先为容易的部分。在您的Web应用程序项目(WAP)中创建一个名为app_offline-template.htm的文件。这将是目标服务器上的app_offline.htm文件。如果您将其留空,您的用户将收到一条通用消息,指出应用程序处于脱机状态,但是最好将静态HTML(无ASP.NET标记)放在该文件中,让用户知道该站点会回来以及您认为与您的用户相关的其他任何信息。添加此文件时,应将属性网格中的构建操作更改为无。这将确保此文件本身未发布/打包。由于文件以.htm结尾将默认发布。见下图。
现在很难的部分。对于Web应用程序项目,我们将钩子发布到/包进程中,我们称之为“wpp.targets”。如果要扩展发布/打包过程,您可以在与项目文件本身相同的文件夹中创建名为{ProjectName} .wpp.targets的文件。这是我创建的文件,您可以将内容复制并粘贴到wpp.targets文件中。我会解释重要的部分,但想要发布整个文件为您的说服。注意:您可以从我的github repo中获取我的最新版本的文件,链接位于下面的资源部分。
<?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
现在我们的应用程序已发布,我们需要从dest Web应用程序中删除app_offline.htm文件。 msdeploy.exe命令将是:
%msdeploy%
-verb:删除
-dest:的contentPath = “{IIS路径} /app_offline.htm”,计算机名= “… ”用户名=“ … ”密码=“ …”
这是在DeleteAppOffline目标中实现的。此目标将在发布后自动执行,因为我已经包含属性AfterTargets =“MSDeployPublish”。在该目标中,您可以看到我正在直接构建msdeploy.exe命令,看起来MSDeploy任务不支持删除动词。
如果你尝试这个,请让我知道,如果你遇到任何问题。我正在考虑从中创建一个Nuget包,以便您可以安装该包。这将需要一些工作,所以请让我知道如果你有兴趣的话。
资源
> The latest version of my AppOffline wpp.targets file
> ScottGu’s blog on app_offline.htm