net - App_Offline en MSBuild Remote Web Deploy
net core 2.1 publish exe (2)
Ahora esto es compatible con WebDeploy v3.0 ... todo lo que necesita hacer es agregar esta línea en su perfil de publicación en ''Propiedades / Perfiles de publicación''
<EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>
Por lo tanto, el perfil de publicación resultante será similar al siguiente.
<?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>
He probado esto y me desconecta de la aplicación durante la implementación, pero desafortunadamente, de vez en cuando, aparece el error "PrecompiledApp.config está en uso".
Puede encontrar más información sobre esto aquí: http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksum.aspx
Tengo la siguiente tarea en mi script de MSBuild para desplegar en un servidor remoto utilizando Web Deploy (servicio 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>
Funciona bien. Sin embargo, me gustaría colocar un archivo app_offline.htm (en el servidor remoto) antes de implementar la aplicación y eliminar el archivo app_offline.htm después de la implementación (o en caso de error). ¿Hay alguna propiedad de MSBuild o alguna otra modificación de scripting para que esto suceda?
Gracias por adelantado.
Recientemente publiqué un blog sobre esto en http://sedodream.com/2012/01/08/HowToTakeYourWebAppOfflineDuringPublishing.aspx . Es más difícil de lo que debería y estoy trabajando en simplificar eso para una versión posterior. En cualquier caso, he pegado todo el contenido aquí para ti.
Recibí un correo electrónico de un cliente preguntándome cómo pueden desconectar su aplicación / sitio web durante todo el tiempo que esté ocurriendo una publicación desde Visual Studio. Una forma fácil de desconectar su sitio es colocar un archivo app_offline.htm en el directorio raíz del sitio. Para obtener más información sobre eso, puede leer la publicación de ScottGu, enlace en la sección de recursos a continuación. Desafortunadamente, Web Deploy no soporta esto. Si desea que Web Deploy (también conocido como MSDeploy) sea compatible de forma nativa con esta función, vote sobre ella en http://aspnet.uservoice.com/forums/41199-general/suggestions/2499911-take-my-site-app-offline-during-publishing .
Dado que Web Deploy no admite esto, va a ser un poco más difícil y requiere que realicemos los siguientes pasos:
- Publicar app_offline.htm
- Publique la aplicación y asegúrese de que app_offline.htm esté contenido dentro de la carga útil que se publica.
- Eliminar app_offline.htm
1 desconectará la aplicación antes de que comience el proceso de publicación.
2 se asegurará de que cuando publiquemos ese app_offline.htm no se elimine (y por lo tanto mantenga la aplicación fuera de línea)
3 eliminará app_offline.htm y pondrá el sitio de nuevo en línea
Ahora que sabemos lo que hay que hacer, veamos la implementación. Primero por la parte fácil. Cree un archivo en su Proyecto de aplicación web (WAP) denominado app_offline-template.htm. Este será el archivo que terminará siendo el archivo app_offline.htm en su servidor de destino. Si lo deja en blanco, sus usuarios recibirán un mensaje genérico que indica que la aplicación está fuera de línea, pero sería mejor para usted colocar HTML estático (sin marca ASP.NET) dentro de ese archivo para que los usuarios sepan que el sitio volverá. y cualquier otra información que creas relevante para tus usuarios. Cuando agregue este archivo, debe cambiar la Acción de compilación a Ninguna en la cuadrícula de Propiedades. Esto asegurará que este archivo en sí no esté publicado / empaquetado. Como el archivo finaliza en .htm, se publicará de forma predeterminada. Vea la imagen de abajo.
Ahora para la parte difícil. Para proyectos de aplicaciones web tenemos un gancho en el proceso de publicación / paquete al que nos referimos como "wpp.targets". Si desea extender su proceso de publicación / paquete, puede crear un archivo llamado {ProjectName} .wpp.targets en la misma carpeta que el archivo del proyecto. Aquí está el archivo que creé, puede copiar y pegar el contenido en su archivo wpp.targets. Explicaré las partes significativas, pero quería publicar todo el archivo para convencerlo. Nota: puede obtener mi última versión de este archivo de mi repositorio de github, el enlace se encuentra en la sección de recursos a continuación.
<?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 Publicar app_offline.htm
La implementación para # 1 está contenida dentro del PublishAppOfflineToDest de destino. El comando msdeploy.exe que debemos ejecutar es.
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
Para hacer esto, aprovecharé la tarea MSDeploy. Dentro del destino PublishAppOfflineToDest puede ver cómo se logra esto creando un elemento tanto para el origen como para el destino.
2 Publique la aplicación y asegúrese de que app_offline.htm esté contenido dentro de la carga útil que se publica.
Esta parte es cumplida por el fragmento.
<!--***********************************************************************
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>
El valor del elemento para FilesForPackagingFromProject aquí convertirá su app_offline-template.htm a app_offline.htm en la carpeta desde donde se procesará la publicación. También hay una condición para que solo ocurra durante la publicación y no en el empaquetado. No queremos que app_offline-template.htm esté en el paquete (pero tampoco es el fin del mundo).
El elemento para MsDeploySkiprules se asegurará de que app_offline-template.htm no se publique. Esto puede no ser necesario pero no debería doler.
3 Eliminar app_offline.htm
Ahora que nuestra aplicación está publicada, necesitamos eliminar el archivo app_offline.htm de la aplicación web de destino. El comando msdeploy.exe sería:
% msdeploy% -verb: delete -dest: contentPath = "{IIS-Path} /app_offline.htm", computerName = "...", username = "...", password = "..."
Esto se implementa dentro del objetivo DeleteAppOffline. Este objetivo se ejecutará automáticamente después de la publicación porque he incluido el atributo AfterTargets = "MSDeployPublish". En ese destino, puede ver que estoy compilando el comando msdeploy.exe directamente, parece que la tarea MSDeploy no admite el verbo de eliminación.
Si prueba esto, por favor avíseme si tiene algún problema. Estoy pensando en crear un paquete Nuget a partir de esto para que pueda instalar ese paquete. Eso tomaría un poco de trabajo, así que avísame si estás interesado en eso.