App_Offline в MSBuild Remote Web Deploy - PullRequest
       86

App_Offline в MSBuild Remote Web Deploy

22 голосов
/ 30 января 2012

У меня есть следующая задача в моем скрипте 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 или другие скриптовые настройки, чтобы это произошло?

Заранее спасибо.

Ответы [ 2 ]

22 голосов
/ 30 января 2012

Я недавно писал об этом на http://sedodream.com/2012/01/08/HowToTakeYourWebAppOfflineDuringPublishing.aspx. Это сложнее, чем должно быть, и я работаю над упрощением этого для более поздней версии. В любом случае, я вставил сюда весь контент для вас.

Я получил электронное письмо от клиента, спрашивающее, как они могут перевести свое веб-приложение / сайт в автономный режим на весь период публикации в Visual Studio. Простой способ перевести ваш сайт в автономный режим - это поместить файл app_offline.htm в корневой каталог сайтов. Более подробную информацию об этом вы можете прочитать в сообщении ScottGu, перейдя по ссылке ниже в разделе ресурсов. К сожалению, сам Web Deploy не поддерживает это. Если вы хотите, чтобы Web Deploy (он же MSDeploy) изначально поддерживал эту функцию, проголосуйте за нее по номеру http://aspnet.uservoice.com/forums/41199-general/suggestions/2499911-take-my-site-app-offline-during-publishing.

Поскольку Web Deploy не поддерживает это, это будет немного сложнее, и для этого нам потребуется выполнить следующие шаги:

  1. Опубликовать app_offline.htm
  2. Опубликуйте приложение и убедитесь, что app_offline.htm содержится в публикуемой полезной нагрузке
  3. Удалить app_offline.htm

1 переведет приложение в автономный режим до начала процесса публикации.

2 гарантирует, что при публикации app_offline.htm не будет удален (и, следовательно, будет держать приложение в автономном режиме)

3 удалит app_offline.htm и вернет сайт в режим онлайн

Теперь, когда мы знаем, что нужно сделать, давайте посмотрим на реализацию. Сначала для легкой части. Создайте файл в своем проекте веб-приложения (WAP) с именем app_offline-template.htm. Это будет файл, который в конечном итоге станет файлом app_offline.htm на целевом сервере. Если вы оставите это поле пустым, ваши пользователи получат общее сообщение о том, что приложение находится в автономном режиме, но для вас было бы лучше поместить статический HTML (без разметки ASP.NET) внутри этого файла, чтобы пользователи знали что сайт вернется и любую другую информацию, которая, по вашему мнению, имеет отношение к вашим пользователям. Когда вы добавляете этот файл, вы должны изменить действие сборки на «Нет» в сетке свойств. Это гарантирует, что сам этот файл не будет опубликован / упакован. Поскольку файл заканчивается на .htm, он будет по умолчанию опубликован. Смотрите изображение ниже.

enter image description here

Теперь самое сложное. Для проектов веб-приложений у нас есть хук в процессе публикации / упаковки, который мы называем «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 был в пакете (но это не конец света, если он тоже).

Элементt для MsDeploySkiprules позаботится о том, чтобы сам app_offline-template.htm не публиковался.Это может не требоваться, но не должно причинять вреда.

3 Удалить app_offline.htm

Теперь, когда наше приложение опубликовано, нам нужно удалить файл app_offline.htm из веб-приложения dest.Команда 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
13 голосов
/ 29 ноября 2013

Это теперь поддерживается WebDeploy v3.0 .. все, что вам нужно сделать, это добавить эту строку в свой профиль публикации в «Свойства \ PublishProfiles»

<EnableMSDeployAppOffline>true</EnableMSDeployAppOffline>

Таким образом, итоговый профиль публикации будет выглядеть как-токак показано ниже.

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

Я проверил это, и мое приложение отключается во время развертывания, но, к сожалению, я все еще иногда получаю ошибку «PrecompiledApp.config is used».

Более подробную информацию об этом можно найти здесь: http://blogs.msdn.com/b/webdev/archive/2013/10/30/web-publishing-updates-for-app-offline-and-usechecksum.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...