Использование MsBuild для создания настраиваемого манифеста MsDeploy (целевой объект пакета) - PullRequest
18 голосов
/ 15 сентября 2011

Я использую Web Deploy для упаковки и развертывания веб-сайтов для моего продукта. В частности, в моем решении есть два разных проекта, которые я использую для развертывания.

У меня есть третий проект в решении (служба Windows), который также должен быть установлен на веб-сервере.

Я знаю, что могу написать собственный манифест (для провайдеров dirPath, filePath и runCommand) и напрямую вызвать MsDeploy для его развертывания. Но я хотел бы использовать существующие задачи MsBuild для упаковки моего сервиса, если это возможно.

Я вижу, что можно сделать некоторые настройки файла манифеста с помощью целей msbuild:

http://social.msdn.microsoft.com/Forums/en/msbuild/thread/1044058c-f762-456b-8a68-b0863027ce47

В частности, с помощью элемента MsDeploySourceManifest.

После просмотра соответствующих файлов .targets, похоже, либо contentPath, либо iisApp будут добавлены в мой манифест, если я использую цель Package. В идеале я просто хотел бы скопировать сборку (или каталог), возможно установить ACL и выполнить installutil.exe в службе.

Можно ли полностью настроить манифест, сгенерированный целью Package, отредактировав мой файл csproj?

Если нет, то есть ли простой способ создать новую цель, которая будет эквивалентна Package, и все же разрешить мне выложить совершенно собственный манифест?

1 Ответ

17 голосов
/ 22 ноября 2011

У меня пока нет полной записи для людей, пытающихся узнать, как это работает, но теперь у меня есть запись о том, как хотя бы достичь этой цели.

http://thehappypath.net/2011/11/21/using-msdeploy-for-windows-services/

( edit: ссылка пока неактивна. Дайте мне знать, если вы заинтересованы, и я могу опубликовать ее в другом месте ).

Мой гид проходит следующие общие шаги:

  • Убедитесь, что служба запускается после установки (не важно, но проще в обращении)
  • Добавьте файл Microsoft.WebApplication.targets в свой проект, даже если у вас нет веб-проекта. Это включает цель Package MsBuild.
  • Добавить пользовательский файл .targets в проект, который создает собственный манифест пакета MsBuild
  • Добавьте несколько пакетных скриптов в свой проект, чтобы остановить / удалить и установить службу
  • Добавить файл Parameters.xml для поддержки более простого изменения целевого каталога развертывания
  • Настройка преобразований app.config с использованием дополнения SlowCheetah Visual Studio

Затем вы можете упаковать свой проект с помощью этой командной строки:

msbuild MyProject.csproj /t:Package /p:Configuration=Debug

Вы можете развернуть полученный пакет с помощью следующей командной строки:

MyService.Deploy.cmd /Y /M:mywebserver -allowUntrusted

Самой недокументированной частью этого (кроме моего руководства) является создание собственного манифеста. Вот дамп моего текущего файла (обратите внимание, он все еще немного глючит, но может быть исправлен - см. Этот вопрос: MsDeploy remoting выполняет манифест дважды - и попытайтесь использовать only прямые командные файлы для runCommand).

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build"
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!-- This file must be included before Microsoft.Web.Publishing.targets so we can hook into BeforeAddIisSettingAndFileContentsToSourceManifest -->

  <PropertyGroup>

    <!-- Include our targets -->
    <IncludeStopServiceCommand>True</IncludeStopServiceCommand>
    <IncludeSetCustomAclsProvider>True</IncludeSetCustomAclsProvider>
    <IncludeInstallServiceCommand>True</IncludeInstallServiceCommand>
    <IncludeMoveAppConfigToCorrectPackagePath>True</IncludeMoveAppConfigToCorrectPackagePath>

    <!-- Uncomment to enable more verbose MsBuild logging -->
    <!-- <EnablePackageProcessLoggingAndAssert>True</EnablePackageProcessLoggingAndAssert> -->

    <!-- Enable web.config transform, but hack it to work for app.config -->
    <ProjectConfigFileName>app.config</ProjectConfigFileName>
    <TransformWebConfigEnabled>True</TransformWebConfigEnabled>
    <UseParameterizeToTransformWebConfig>True</UseParameterizeToTransformWebConfig>

    <!-- Enable web project packaging, but hack it to work for non-web app -->
    <DeployAsIisApp>False</DeployAsIisApp>
    <IncludeIisSettingsOnPublish>False</IncludeIisSettingsOnPublish>
    <IncludeSetAclProviderOnDestination>False</IncludeSetAclProviderOnDestination>
    <DisableAllVSGeneratedMSDeployParameter>True</DisableAllVSGeneratedMSDeployParameter>

    <!-- Insert our custom targets into correct places in build process -->
    <BeforeAddIisSettingAndFileContentsToSourceManifest Condition="'$(BeforeAddIisSettingAndFileContentsToSourceManifest)'==''">
      $(BeforeAddIisSettingAndFileContentsToSourceManifest);
      AddStopServiceCommand;
    </BeforeAddIisSettingAndFileContentsToSourceManifest>

    <AfterAddIisSettingAndFileContentsToSourceManifest Condition="'$(AfterAddIisSettingAndFileContentsToSourceManifest)'==''">
      $(AfterAddIisSettingAndFileContentsToSourceManifest);
      AddSetCustomAclsProvider;
      AddInstallServiceCommand;
    </AfterAddIisSettingAndFileContentsToSourceManifest>

    <OnAfterCopyAllFilesToSingleFolderForPackage Condition="'$(OnAfterCopyAllFilesToSingleFolderForPackage)'==''">
      $(OnAfterCopyAllFilesToSingleFolderForPackage);
      MoveAppConfigToCorrectPackagePath;
    </OnAfterCopyAllFilesToSingleFolderForPackage>

  </PropertyGroup>

  <!-- Custom targets -->
  <Target Name="AddStopServiceCommand" Condition="'$(IncludeStopServiceCommand)'=='true'">
    <Message Text="Adding runCommand to stop the running Service" />
    <ItemGroup>

      <MsDeploySourceManifest Include="runCommand">
        <path>$(_MSDeployDirPath_FullPath)\bin\servicestop.bat</path>
        <waitInterval>20000</waitInterval>
        <AdditionalProviderSettings>waitInterval</AdditionalProviderSettings>
      </MsDeploySourceManifest>

    </ItemGroup>
  </Target>

  <Target Name="AddSetCustomAclsProvider" Condition="'$(IncludeSetCustomAclsProvider)'=='true'">
    <ItemGroup>

      <MsDeploySourceManifest Include="setAcl">
        <Path>$(_MSDeployDirPath_FullPath)</Path>
        <setAclUser>LocalService</setAclUser>
        <setAclAccess>FullControl</setAclAccess> <!-- Todo: Reduce these permissions -->
        <setAclResourceType>Directory</setAclResourceType>
        <AdditionalProviderSettings>setAclUser;setAclAccess;setAclResourceType</AdditionalProviderSettings>
      </MsDeploySourceManifest>

    </ItemGroup>
  </Target>

  <Target Name="AddInstallServiceCommand" Condition="'$(IncludeInstallServiceCommand)'=='true'">
    <Message Text="Adding runCommand to install the Service" />
    <ItemGroup>

      <MsDeploySourceManifest Include="runCommand">
        <path>cmd.exe /c $(_MSDeployDirPath_FullPath)\bin\serviceinstall.bat</path>
        <waitInterval>20000</waitInterval>
        <dontUseCommandExe>false</dontUseCommandExe>
        <AdditionalProviderSettings>waitInterval;dontUseCommandExe</AdditionalProviderSettings>
      </MsDeploySourceManifest>

    </ItemGroup>
  </Target>

  <Target Name="MoveAppConfigToCorrectPackagePath"
          Condition="'$(IncludeMoveAppConfigToCorrectPackagePath)'=='true'">
    <PropertyGroup>
      <OriginalAppConfigFilename>$(_PackageTempDir)\App.Config</OriginalAppConfigFilename>
      <TargetAppConfigFilename>$(_PackageTempDir)\bin\$(TargetFileName).config</TargetAppConfigFilename>
    </PropertyGroup>

    <Copy SourceFiles="$(OriginalAppConfigFilename)" DestinationFiles="$(TargetAppConfigFilename)" 
          Condition="Exists($(OriginalAppConfigFilename))" />
    <Delete Files="$(OriginalAppConfigFilename)" 
            Condition="Exists($(OriginalAppConfigFilename))" />
  </Target>

</Project>
...