Как сделать windows installer

В статье я хотел бы поделиться своим опытом написания инсталлятора для Windows с использованием инструмента Windows Installer XML Toolset (далее — Wix). К сожалению, несмотря на всю мощь данного инструмента, его использование сильно осложняется куцей документацией, старенькими кукбуками, вялыми ветками форумов и вытеснением .msi и .exe пакетов контейнеризацией. Однако, сегодня продолжают активно развиваться и создаваться программные продукты требующие развертывания на виндовой машине с использованием традицонных установочных пакетов.

Прежде, чем мы преступим к написанию инсталлятора нужно решить, что мы будем устанавливать. По большому счету, инструментарий Wix не ограничивает разработчика в технологиях на которых должен быть написан продукт, который будет развернут на машине пользователя. Главное условие, чтобы на машине пользователя была установлена соответствующая версия Windows с пакетами, необходимыми для запуска вашего продукта (кстати, wix позволяет в установочный пакет запихнуть в том числе и необходимые компоненты для настройки окружения, но об этом поговорим позже).

Для нашего инсталлятора предлагаю использовать дефолтный проект Blazor: с одной стороны нам не потребуется писать код устанавливаемого проекта, а с другой у нас будет достаточно высокий потенциал для костылизации, чтобы изучить возможности Wix toolset.

Теория

Прежде чем приступить к практической части предлагаю ускоренный ликбез по технологии Windows installer и wix toolset, что поможет читателю понять мотивы, которыми руководствуются команды разработчиков вставая на путь, вымощенный граблями.

Начнем с того, что Wix toolset – это набор инструментов, позволяющий создавать установочные пакеты Windows installer на основе .xml-описания, который включает в себя консольные утилиты, плагин для работы Visual Studio и Rider, несколько тем оформления инсталлятора (глобально они отличаются «глубиной» диалогов, определяющей свободу пользователя в процессе установки), а также средства создания бутстрапера (пожалуй, дословный перевод «установщик» в данном случае не особо применим).

Windows installer, в свою очередь, представляет собой подсистему Windows для развертывания программного обеспечения с использованием установочных пакетов .msi (Microsoft Installer). Не погружаясь в историю создания и эволюции данной подсистемы (кому интересно, можете поискать информацию о инсталляторе с кодовым названием Darwin) предлагаю сразу перейти к ее функционалу.

Так, ключевую ценность данной подсистемы представляет высокая гибкость процесса установки, обновления и удаления программ, что обеспечивается:

  • Возможностью отката на любом этапе установки включая апгрейд и удаление софта

  • Предоставлением доступа к работе с реестрами включая чтение и удаление записей

  • Гибкостью работы с правами доступа при установке софта

  • Обеспечением возможности кастомизации интерфейса установки, включая возможность добавления рекламы

  • Предоставлением доступа к ресурсам командной строки и возможности запуска скриптов на разных этапах работы инсталлятора

  • Наличием специализированного ПО, предоставляемого Microsoft для устранения проблем, возникших после запуска инсталляционного пакета с уязвимостью (например, если ошибка приводит к невозможности удаления установленного софта)

Сам инсталлятор представляет собой файл с расширением .msi внутри которого располагается реляционная база данных, описывающая логику установки программного обеспечения, а также хранит данные, необходимые для развертывания приложения. Для работы с инсталляционными пакетами вам потребуется установить Windows SDK. Основным инструментом для взаимодействия с файлами .msi является Orca – программа, позволяющая открывать, редактировать и создавать БД инсталляционных пакетов. Для ее установки вам потребуется перейти в директорию C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x86 после установки Windows SDK.

Давайте посмотрим на пример содержимого инсталляционного пакета, который мы с вами создадим с помощью WIX для проекта Blazor. Его содержимое выглядит так:

В приведенном примере инсталлятор содержит 35 таблиц. Это число не является фиксированным. Только Orca предлагает включение до 97 шаблонов таблиц, помимо которых можно создавать пользовательские.

Разберем по пунктам:

  • в колонке File хранится ID файла, который будет установлен в систему. Он выполняет роль первичного ключа для доступа и связывает сущности из таблицы MsiFileHash и Component

  • В Component_ лежит значение соответствующее полю KeyPath из таблицы Component, которое служит для реализации функционала, связанного с восстановлением и обновлением ПО средствами WindowsInstaller

  • В FileName хранится непосредственно имя файла

  • FileSize, Version и Language берутся из метаданных устанавливаемого файла

  • Atributes – свойства устанавливаемого файла, определяющие его доступность для пользователей, а также поведение при обновлении, восстановлении и удалении продукта. Подробнее можно ознакомиться по ссылке

  • Sequence определяет положение файла в инсталляторе и должен соответствовать его номеру в cabinet-файле.

Если, вы еще не сильно утомились сухой теорией, то давайте посмотрим еще на одну ключевую таблицу – Component:

В этой таблице описаны компоненты:  .

  • В колонке Component лежит название компонента, которое должно быть уникальным. Оно может быть создано как разработчиком, так и средствами автоматизации. Главное, что с помощью этого значения компонент связывается с файлом, который будет в него завернут.

  • ComponentId – GUID, который должен быть сгенерирован для каждого компонента. Фактически это первичный ключ в таблице компонентов.

  • Колонка Directory_ связывает компонент с виртуальной директорией, которая будет ассоциирована с местом установки конкретного компонента.

Думаю, на этом кратенький рассказ о внутреннем устройстве базы данных пакета .msi можно закончить. Конечно, кроме файлов, компонентов и папок, база данных инсталлятора включает описание опций (feature), действий (action), UI и пр. При наличии интереса у читателей, готов подготовить более подробный обзор структуры .msi пакетов.

Практика

Для того, чтобы упростить разработку инсталляционных пакетов и облегчить дальнейшую поддержку были разработаны различные инструменты, позволяющие визуализировать и автоматизировать некоторые рутинные процессы. К таким продуктам, например, относятся InstallShield, InnoSetup (не позволяет создавать .msi-файлы — только .exe) и AdvancedInstaller. Несмотря на удобство использования, данные продукты являются платными (стоимость некоторых продуктов довольно кусачая за исключением Inno Setup — он бесплатный), не имеют открытых репозиториев или создают сложности при корпоративной разработке при мерже проектов. Поэтому наиболее очевидным выбором для большинства интерпрайз-проектов является использование The Windows Installer XML (WiX) toolset.

Для начала работы с этим инструментом вам необходимо произвести его установку. Перейдите по ссылке и скачайте и установите WiX Toolset build tools и WiX Toolset Visual Studio Extension (в соответствии с используемой вами версией Visual Studio). Также, есть расширение для Rider – его можно найти в маркете IDE.

После установки компонентов Wix предлагаю перейти в Visual Studio и приступить к созданию проекта Blazor для которого мы будем писать инсталлятор.

Создадим проект Blazor Wasm и опубликуем его

File -> New Project -> Blazor WebAssambly App. Назовем проект BlazorAppForInstaller.

На следующем шаге обязательно поставьте галочку ASP.NET Core hosted и выберите .Net 6.0.

После того как проект был создан опубликуем его:

Щелкнуть правой кнопкой мыши по BlazorAppForInstaller.Server -> Publish -> Target: Folder -> Finish.

Проект должен быть опубликован в указанную вами папку (в моем случае, это ~\BlazorAppForInstaller\Server\bin\Release\net6.0\publish\): содержимое этой директории мы и будем упаковывать в инсталлятор.

Создадим проект Wix InstallerForBlazorApp

Щелкнуть правой кнопкой мыши по названию решения Add -> New project

В поиске вбиваем Wix

В результатах поиска выбираем Setup Project for Wix v3 и нажимаем Next

В поле Project name вводим названием. В моем случае это InstallerForBlazorApp. Щелкаем по кнопке Create.

Настройка проекта

Для сборки инсталлятора необходимо описать компоненты (то есть файлы установки).

Если бы мы имели дело с простым проектом, состоящим из десятка файла, то вполне допустимо их описать вручную. Однако, когда речь заходит о суровой интерпрайз разработке или просто о больших проектах, включающих кучу файлов (особенно это касается веба) довольно сложно (а зачастую невозможно) становится следить за добавлением или удалением файлов. Именно поэтому, мы воспользуемся консольной утилитой Harvest Tool (heat.exe), который можно найти в директории ~/WiX Toolset v3.11\bin (по умолчанию, должна быть создана при установке в C:/Program Files (x86)). Подробно ознакомиться с возможностями Heat.exe можно в официальной документации https://wixtoolset.org/documentation/manual/v3/overview/heat.html

Я предлагаю сделать запуск heat.exe частью сборки проекта, чтобы сэкономить силы в процессе разработки – благо проекты Wix позволяют интегрировать генерацию описания непосредственно в файл проекта .wixproj.

Щелкаем правой кнопкой мыши по проекту инсталлятора -> Add Reference — открываем папку, в которую был установлен WiX, подкаталог bin, файл WixUtilExtension.dll

С использованием любого текстового редактора откройте файл InstallerForBlazorApp.wixproj и вставьте следующий кусок кода перед закрывающимся тегом </Project>

<Target Name="BeforeBuild">
    <PropertyGroup>
      <DefineConstants>
        BasePath=..\..\BlazorAppForInstaller\BlazorAppForInstaller\Server\bin\Release\net6.0\publish;
      </DefineConstants>
    </PropertyGroup>
    <!--This code generates the ComponentsGeneration.wxs 
    which describes the components to include into the installer.-->
    <HeatDirectory 
    OutputFile="ComponentsGenerated.wxs" 
    DirectoryRefId="INSTALLFOLDER" 
    ComponentGroupName="PublishedComponents" 
    SuppressCom="true" 
    Directory="..\..\BlazorAppForInstaller\BlazorAppForInstaller\Server\bin\Release\net6.0\publ ish" 
    SuppressFragments="true" 
    SuppressRegistry="true" 
    SuppressRootDirectory="true" 
    AutoGenerateGuids="false" 
    GenerateGuidsNow="true" 
    ToolPath="$(WixToolPath)" 
    PreprocessorVariable="var.BasePath" 
    RunAsSeparateProcess="$(RunWixToolsOutOfProc)" />
</Target>

Как вы видите, код помещен внутрь тега <Target Name=”BeforeBuild”> описывающий действия, которые должны быть выполнены непосредственно перед сборкой инсталлятора. К таким действиям относится объявление констант препроцессора, к которым можно будет обращаться до этапа сборки проекта. Так, переменная (да, это константа, но нейминг Wix периодически противоречит самому себе) BasePath используется для обозначения пути проекта, который будет упакован в инсталлятор. Настоятельно рекомендую использовать относительные пути настолько насколько это возможно.

Далее, с помощью тега <Heat> и его свойств мы вызываем утилиту Heat.exe и передаем ей необходимые аргументы:

  • OutputFile="ComponentsGenerated.wxs" – путь до файла, в котором хранятся компоненты для установки

  • DirectoryRefId="INSTALLFOLDER" – ссылка на папку в которую будет произведена установка приложения (по сути это переменная в которую будет записан путь до директории установки)

  • ComponentGroupName="PublishedComponents" – наименование группы компонентов, которые были сгенерированы. Используется как алиас для множества компонентов и является абстракцией, существующей исключительно в рамках проект Wix. Когда инсталлятор будет скомпилирован, то в таблицах .msi файла вы не найдете сущности соответствующей группе компонентов

  • AutoGenerateGuids="false" и GenerateGuidsNow="true" – настройка генерирации GUID для компонентов в момент вызова утилиты Heat. Такая конфигурация заставляет Heat создать для каждого компонента уникальный GUID в момент запуска таски, т.е. на этапе сборки проекта. Такой подход минимизирует количество ошибок, возникающих при компиляции проекта Wix.

  • ToolPath="$(WixToolPath)" – путь до директории с установленным Wix Toolset. Рекомендую использовать переменную окружения WixToolPath, которая создается при установке Wix. По большому счету, прописывать вручную путь придется только в том случае, если вы планируете использовать Wix toolset без установки через стандартный инсталлятор.

  • PreprocessorVariable="var.BasePath" – переменная препроцессора, которая используется в качестве части пути (указывает на директорию) до файла-компонента. Мы ее объявили внутри тега <DefineConstants>

  • RunAsSeparateProcess="$(RunWixToolsOutOfProc)"– обязательно указывайте этот атрибут, если работаете в Visual Studio 2022 и собираете 64-битный проект. В противном случае Visual Studio будет закрываться при каждой попытке построить проект. Эту проблему обсуждали здесь

  • SuppressRootDirectory="true" – необходим для избежания дублирования родительских папок компонента.

  • SuppressCom="true", SuppressFragments="true" и SuppressRegistry="true" – несмотря на то, что очень не велика вероятность, что в вашем проекте окажутся COM объекты, файлы реестров и фрагменты установщика лежащие в одной папке с основным проектом, рекомендуется дополнительно запретить включать такие файлы в процесс создания описания компонентов из-за высокой вероятности возникновения ошибок. Если же, у вас есть необходимость включения таких файлов в проект инсталлятора, рекомендуется добавить отдельное описание таких компонентов.

После внесенных изменений InstallerForBlazorApp.wixproj должен выглядеть так

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">x64</Platform>
    <ProductVersion>3.10</ProductVersion>
    <ProjectGuid>6f99cf2a-a8d3-4f08-a4e1-cd86ea9c9785</ProjectGuid>
    <SchemaVersion>2.0</SchemaVersion>
    <OutputName>InstallerForBlazorApp</OutputName>
    <OutputType>Package</OutputType>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
    <OutputPath>bin\$(Configuration)\</OutputPath>
    <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
    <DefineConstants>Debug</DefineConstants>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
    <OutputPath>bin\$(Configuration)\</OutputPath>
    <IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="ComponentsGenerated.wxs" />
    <Compile Include="IISConfiguration.wxs" />
    <Compile Include="Product.wxs" />
  </ItemGroup>
  <ItemGroup>
    <WixExtension Include="WixUtilExtension">
      <HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
      <Name>WixUtilExtension</Name>
    </WixExtension>
    <WixExtension Include="WixUIExtension">
      <HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
      <Name>WixUIExtension</Name>
    </WixExtension>
    <WixExtension Include="WixIIsExtension">
      <HintPath>$(WixExtDir)\WixIIsExtension.dll</HintPath>
      <Name>WixIIsExtension</Name>
    </WixExtension>
  </ItemGroup>
  <Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
  <Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
    <Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
  </Target>
  <Target Name="BeforeBuild">
    <PropertyGroup>
      <DefineConstants>
        BasePath=..\..\BlazorAppForInstaller\BlazorAppForInstaller\Server\bin\Release\net6.0\publish;
      </DefineConstants>
    </PropertyGroup>
    <!--This code generates the ComponentsGeneration.wxs 
    which describes the components to include into the installer.-->
    <HeatDirectory OutputFile="ComponentsGenerated.wxs" DirectoryRefId="INSTALLFOLDER" ComponentGroupName="PublishedComponents" SuppressCom="true" Directory="..\..\BlazorAppForInstaller\BlazorAppForInstaller\Server\bin\Release\net6.0\publish" SuppressFragments="true" SuppressRegistry="true" SuppressRootDirectory="true" AutoGenerateGuids="false" GenerateGuidsNow="true" ToolPath="$(WixToolPath)" PreprocessorVariable="var.BasePath" RunAsSeparateProcess="$(RunWixToolsOutOfProc)" />
  </Target>
</Project>

После того, как вы внесете указанные изменения в файл .wixproj сохраните изменения и постройте проект. В результате, в корневой папке проекта инсталлятора должен появиться файл ComponentsGenerated.wxs.

В моем случае ComponentGenerated.wxs имеет следующее содержание

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Fragment>
        <DirectoryRef Id="INSTALLFOLDER">
            <Component Id="cmpA0863526952F7834E7C922F065E4C8A8" Guid="{4F47DA2F-E8FD-4B92-AE61-FFE9CA68BF7F}">
                <File Id="filC04B02D0CCC2D5CCC1013B35DE86DB29" KeyPath="yes" Source="$(var.BasePath)\appsettings.Development.json" />
            </Component>
            <Component Id="cmpF82FCA80BBAF44D285C97F10993DEEE6" Guid="{EE55FE38-515B-444C-9496-6BA0FE9F8550}">
                <File Id="fil840B80AC19861C7F9F04FBDCFAE331CE" KeyPath="yes" Source="$(var.BasePath)\appsettings.json" />
            </Component>
            <Component Id="cmp80A32365AE3ACFE27BDD385AE91DCE74" Guid="{2234C1AC-AB8D-460E-BBF1-F982BBE28426}">
                <File Id="filA65D0C2EEDE361CBA6DAA5414A5885D6" KeyPath="yes" Source="$(var.BasePath)\BlazorAppForInstaller.Client.dll" />
            </Component>
            <Component Id="cmpF69BDBE9F42451436A0B8C022F6D4636" Guid="{291B8DF2-FC5A-4C41-94A8-2100BC13DA52}">
                <File Id="filEF7A1D8322B02801B5E1FF05C1E9C211" KeyPath="yes" Source="$(var.BasePath)\BlazorAppForInstaller.Client.pdb" />
            </Component>
            <Component Id="cmpFD59DF07063AC308C40670A4B81A9B57" Guid="{73AF0D36-0704-4458-933B-F8A412BEAF16}">
                <File Id="filEC516099676B2B686B154C6BDD632062" KeyPath="yes" Source="$(var.BasePath)\BlazorAppForInstaller.Server.deps.json" />
            </Component>
            <Component Id="cmpECDF00A9B659260C50885BEEADBCABC0" Guid="{3F5F5E68-208A-4A84-85EC-4C8F3F003760}">
                <File Id="filB052CB4639CA4C158F4D9FE686DB740A" KeyPath="yes" Source="$(var.BasePath)\BlazorAppForInstaller.Server.dll" />
            </Component>
            <Component Id="cmpE351BCDC42EF493685CEF4080E08E51E" Guid="{84BD7DDE-6020-40F9-986B-983174E660F6}">
                <File Id="fil04C3A476D538A356A55E0061D96C252E" KeyPath="yes" Source="$(var.BasePath)\BlazorAppForInstaller.Server.exe" />
            </Component>
            <Component Id="cmp651C3999A00B5D89ACAE2D3A9BE7F91D" Guid="{C497D355-3BD7-45B6-AF99-71F10F687F19}">
                <File Id="fil5845A2249FFDBB31724899C28857297E" KeyPath="yes" Source="$(var.BasePath)\BlazorAppForInstaller.Server.pdb" />
            </Component>
            <Component Id="cmpBCBFD41B8B964007BA9BF340925C6493" Guid="{0AB26848-8B77-49A8-AB82-F6F490C9EB3A}">
                <File Id="fil7883E94C175B382DAE68D2E730B7F18F" KeyPath="yes" Source="$(var.BasePath)\BlazorAppForInstaller.Server.runtimeconfig.json" />
            </Component>
            <Component Id="cmp9A7CD58BE639399F7BDAA987492B6E65" Guid="{840E5F4F-940A-42F4-ABAB-756DA9EEA9A7}">
                <File Id="filC2AF92E94531E79C884299478E78AB02" KeyPath="yes" Source="$(var.BasePath)\BlazorAppForInstaller.Shared.dll" />
            </Component>
            <Component Id="cmpB818026BC106A80C4FD6E90BF8F06CDA" Guid="{6B873FB2-A32E-4AAD-8072-5B6A9B5671D7}">
                <File Id="fil6E77B3E6819A87A3819FFDB52DC2AB74" KeyPath="yes" Source="$(var.BasePath)\BlazorAppForInstaller.Shared.pdb" />
            </Component>
            <Component Id="cmp2F0A313AE6306F9CE5E760AF214DC789" Guid="{9BCD7498-EBD2-460F-A033-6BD934E21DDB}">
                <File Id="fil274A60BD8B17A2DA6C1EB35AEA850F12" KeyPath="yes" Source="$(var.BasePath)\Microsoft.AspNetCore.Authorization.dll" />
            </Component>
            <Component Id="cmp6D6CC90C40E2F632C9128346BA7F188F" Guid="{F0EBBBD6-25A4-4A14-A6A9-3B09FCF616B7}">
                <File Id="filB3A561B406C5673062D93CEAB4C5FBA3" KeyPath="yes" Source="$(var.BasePath)\Microsoft.AspNetCore.Components.dll" />
            </Component>
            <Component Id="cmpA76C6CFFA9DCB201D0EEDB226B0B9E25" Guid="{EE7A5E70-7B9D-4E30-98B8-B39E077D585D}">
                <File Id="fil509B74670E6E3BBFDDC3F98EFB8E8C1D" KeyPath="yes" Source="$(var.BasePath)\Microsoft.AspNetCore.Components.Forms.dll" />
            </Component>
            <Component Id="cmp17959BADF0C2D7B7AB4867F09DA031B8" Guid="{6A5C8273-F71E-43FC-8896-84DD02259470}">
                <File Id="filBCB8CB727FBD0C042A3E896A50A0013A" KeyPath="yes" Source="$(var.BasePath)\Microsoft.AspNetCore.Components.Web.dll" />
            </Component>
            <Component Id="cmpDF4C205418A6D7FE6FEA71F3B8998FAC" Guid="{8AB6FEF4-5925-4C12-B9F4-2A82C8430CDF}">
                <File Id="filC4C0674046FF1CB3C507EAB882BF2E34" KeyPath="yes" Source="$(var.BasePath)\Microsoft.AspNetCore.Components.WebAssembly.dll" />
            </Component>
            <Component Id="cmpDA8B0BBD16E996DE615D6861DBA6442F" Guid="{B1A2B290-F7A5-4BEA-98D6-FA1540E5AF7B}">
                <File Id="fil05438E5B6FC074FE194163CB964F6591" KeyPath="yes" Source="$(var.BasePath)\Microsoft.AspNetCore.Components.WebAssembly.Server.dll" />
            </Component>
            <Component Id="cmp3D2A78302A6149F7464B0EDCD758BCCF" Guid="{D621ED15-E9E3-4BCE-A1F2-226AAF54F6D6}">
                <File Id="fil448E35B6B4567F45DB8A9C0D588396AC" KeyPath="yes" Source="$(var.BasePath)\Microsoft.AspNetCore.Metadata.dll" />
            </Component>
            <Component Id="cmp8C674FD6A69988A60A77A4CEE0F53781" Guid="{F9FCFE30-E9F4-4434-A516-D49A5955838C}">
                <File Id="fil72342637E9F74EE945317D4603CEBA2F" KeyPath="yes" Source="$(var.BasePath)\Microsoft.Extensions.Logging.Abstractions.dll" />
            </Component>
            <Component Id="cmpDB4717CBBFD23A9652DB5B136ABB5D75" Guid="{BF3D8181-57C3-4615-A65A-A356F9749FF0}">
                <File Id="filD208251EAF74D3D9FCA9A0D020CF9631" KeyPath="yes" Source="$(var.BasePath)\Microsoft.JSInterop.dll" />
            </Component>
            <Component Id="cmpCF0F711637230B4D1AE41109C02C9142" Guid="{334AADF3-2C4A-43A3-AA3E-C3063F65C57E}">
                <File Id="fil5E6F1BBD1CE0D66ADA7274CC42146536" KeyPath="yes" Source="$(var.BasePath)\Microsoft.JSInterop.WebAssembly.dll" />
            </Component>
            <Component Id="cmpF88B96E5973E0D28B511DC6371DB06E0" Guid="{0DAA8109-C0F5-47A0-8DC9-FCAAEB8CCC90}">
                <File Id="filA72770FDC08B6447ABAA326398A3C786" KeyPath="yes" Source="$(var.BasePath)\System.IO.Pipelines.dll" />
            </Component>
            <Component Id="cmpB139B49DF4DF8F44C525B449EA8187F7" Guid="{DAD0B80D-AD5E-454B-82EF-1BC3456FB55A}">
                <File Id="filE7A3E65CC622C2E3B9B57707B12C9645" KeyPath="yes" Source="$(var.BasePath)\web.config" />
            </Component>
            <Directory Id="dirFF7B98771B91AAE585FE52B7EFB34AF9" Name="BlazorDebugProxy">
                <Component Id="cmp5B65C45828B950384B8C5C76AB9F6EF0" Guid="{6242E71D-EA64-4F79-A3AA-C661D442FD18}">
                    <File Id="fil0EF0F550322CD17C7C714E44E83269EA" KeyPath="yes" Source="$(var.BasePath)\BlazorDebugProxy\BrowserDebugHost.dll" />
                </Component>
                <Component Id="cmp5A9228A102598245A49CC73E4B42BFFD" Guid="{F6BA6C92-A950-4E24-8C85-448E2CA02DBE}">
                    <File Id="filD8595B9CBE5DD5D704F01D48491D318A" KeyPath="yes" Source="$(var.BasePath)\BlazorDebugProxy\BrowserDebugHost.runtimeconfig.json" />
                </Component>
                <Component Id="cmp0B11C97F8D96134C5A582DAA9D362721" Guid="{CB376EF4-2F26-4D88-A4FA-C8BF3B2C8D1D}">
                    <File Id="fil4E80FEBEAB64C6B7394572A11AEE0A1A" KeyPath="yes" Source="$(var.BasePath)\BlazorDebugProxy\BrowserDebugProxy.dll" />
                </Component>
                <Component Id="cmp22B9B089D6F03FEB02531ECB35C82F8E" Guid="{374B5BC6-6408-49D3-8127-8B5B104DA628}">
                    <File Id="fil6055CEB7DE0EF0D0757B75192036CECF" KeyPath="yes" Source="$(var.BasePath)\BlazorDebugProxy\Microsoft.CodeAnalysis.CSharp.dll" />
                </Component>
                <Component Id="cmp958171B03EC06C56FB11A52D468E5F57" Guid="{CCD5CB55-0760-46EE-9593-7479EE86EDF2}">
                    <File Id="filBE547A9559A6D9185621EABC8B529677" KeyPath="yes" Source="$(var.BasePath)\BlazorDebugProxy\Microsoft.CodeAnalysis.dll" />
                </Component>
                <Component Id="cmpB322B77CE8D40EBAD199D45D0E4F25F0" Guid="{D6CBA61F-4366-482A-B4CA-17E1A68792AD}">
                    <File Id="fil28DEDB3F6C20AB880B95B684491580B0" KeyPath="yes" Source="$(var.BasePath)\BlazorDebugProxy\Newtonsoft.Json.dll" />
                </Component>
            </Directory>
            <Directory Id="dir3D83A529A2122889D4016E7D784625D5" Name="wwwroot">
                <Component Id="cmp920020A0D51F9A626EB2143066649049" Guid="{65310CAD-54CE-4F8D-B0BD-0C8FFA12A329}">
                    <File Id="fil5625CD1F0A436AA0C9E8667328891D3A" KeyPath="yes" Source="$(var.BasePath)\wwwroot\BlazorAppForInstaller.Client.styles.css" />
                </Component>
                <Component Id="cmp6A573805E6F545A7F37C18527646950E" Guid="{67E7C809-BA29-46FC-8ABD-30692E02416D}">
                    <File Id="fil4340641EF92B44F5306114E3F1D36462" KeyPath="yes" Source="$(var.BasePath)\wwwroot\favicon.ico" />
                </Component>
                <Component Id="cmp0D2F1CB83AD7A688791EFF1B2407B5F1" Guid="{5C4C24DA-9BBB-4450-A57B-A5B764EF18C9}">
                    <File Id="filF5852E3A1C173CD4B7AA5BB8D1B19C16" KeyPath="yes" Source="$(var.BasePath)\wwwroot\icon-192.png" />
                </Component>
                <Component Id="cmp8D45D052C68877B0B807B3D45E104FF6" Guid="{6B02277E-69C6-4C6E-B7E0-6F03E23B7467}">
                    <File Id="fil658EB15BA5D7E0782137791A613E6C55" KeyPath="yes" Source="$(var.BasePath)\wwwroot\icon-512.png" />
                </Component>
                <Component Id="cmpD91242D38C41E4403B7679B93F1EEBB4" Guid="{1F0FB915-48FF-46AA-9594-8D5A8D143EA6}">
                    <File Id="filA9C65401D86C7CFD07B966A29B9D89E3" KeyPath="yes" Source="$(var.BasePath)\wwwroot\index.html" />
                </Component>
                <Component Id="cmpCB80CFC92D7C1BB2787B948E67B42B03" Guid="{ACD6D7A5-4812-4E23-B943-8D2D391B1CBE}">
                    <File Id="fil580253134E9F2BB1D7BA130533DE8F04" KeyPath="yes" Source="$(var.BasePath)\wwwroot\manifest.json" />
                </Component>
                <Component Id="cmpBCCB7ADB11BD8E995C2D17B5FDFD7CA8" Guid="{FEA4589A-C26E-4A79-BF72-FA2F9E890FAA}">
                    <File Id="filD26912E52648D14E5D4A954D5F256FA5" KeyPath="yes" Source="$(var.BasePath)\wwwroot\service-worker-assets.js" />
                </Component>
                <Component Id="cmp6300BF95DDDCF98EC047B2991C2BA653" Guid="{D22568BE-81DB-4AB3-902A-B996812E427A}">
                    <File Id="fil54651357683F72D9500F5998771EB4DD" KeyPath="yes" Source="$(var.BasePath)\wwwroot\service-worker.js" />
                </Component>
                <Directory Id="dirED733C34DE106D43E47F9049837C7E99" Name="css">
                    <Component Id="cmp087AEDA3ECF7BE8C1137AADA0E56E0A6" Guid="{E1B47808-2714-4CD6-9862-8D6ECC4BC085}">
                        <File Id="filD9477D05D41C78519460D2E399A53D86" KeyPath="yes" Source="$(var.BasePath)\wwwroot\css\app.css" />
                    </Component>
                    <Directory Id="dir578587A376B13655DF93D8D190D09E38" Name="bootstrap">
                        <Component Id="cmpEBA035EA7685839B21FA1B833C2D781C" Guid="{BD4B431E-4265-459E-85E2-B1FB800041F3}">
                            <File Id="fil9246F4C21320DCC254AAEC2B6CA201E8" KeyPath="yes" Source="$(var.BasePath)\wwwroot\css\bootstrap\bootstrap.min.css" />
                        </Component>
                        <Component Id="cmp87BF3E7D495DC9B53F7ED2A371F1FE92" Guid="{42C20875-5B4E-4020-B569-6F162FF7502E}">
                            <File Id="fil706E0FE7B70A4FE22131C3ECDCC2220D" KeyPath="yes" Source="$(var.BasePath)\wwwroot\css\bootstrap\bootstrap.min.css.map" />
                        </Component>
                    </Directory>
                    <Directory Id="dir4AA45E3B956024607D9673C62D4A5EC7" Name="open-iconic">
                        <Component Id="cmp2220CCF66448F1A862D1353191CE69F5" Guid="{F39CDA89-87A8-4358-9C64-A31535B9FD00}">
                            <File Id="fil69CA8DBC716DB349E38835E0E4376776" KeyPath="yes" Source="$(var.BasePath)\wwwroot\css\open-iconic\FONT-LICENSE" />
                        </Component>
                        <Component Id="cmp791F5746D6F2AC68E2E8A50343B869F7" Guid="{177623EB-7AC3-499E-9AFE-A801224F322D}">
                            <File Id="filAA56F33B7267915E17B9C07E35B9B3B1" KeyPath="yes" Source="$(var.BasePath)\wwwroot\css\open-iconic\ICON-LICENSE" />
                        </Component>
                        <Component Id="cmp3DA139ADE5BC562B564DECE23AFFD8D0" Guid="{18E7BE1D-0F79-49F7-882A-B33029F7D041}">
                            <File Id="fil0A55830EEB5C8115A1BC74E41C184141" KeyPath="yes" Source="$(var.BasePath)\wwwroot\css\open-iconic\README.md" />
                        </Component>
                        <Directory Id="dir71E214D0555C176F3B3EB73000355FD6" Name="font">
                            <Directory Id="dirD56BE8D7B4920E710730E8C5A7AA202D" Name="css">
                                <Component Id="cmp3F52B8D89D587889C8A65D69E74B5F51" Guid="{E1FA7A7E-636C-4A1F-B198-15C7DB660AB8}">
                                    <File Id="fil94C1662E6A729DBD5920B971BE85A743" KeyPath="yes" Source="$(var.BasePath)\wwwroot\css\open-iconic\font\css\open-iconic-bootstrap.min.css" />
                                </Component>
                            </Directory>
                            <Directory Id="dirE412B34DB4EE4DFCC5824E0F7C902C7E" Name="fonts">
                                <Component Id="cmp102AA2B65E2F7CFDBE0F937F8D225168" Guid="{61583E56-78F9-4899-B414-16CF55BA7613}">
                                    <File Id="fil164917E73009BFF1140888BA7311A83E" KeyPath="yes" Source="$(var.BasePath)\wwwroot\css\open-iconic\font\fonts\open-iconic.eot" />
                                </Component>
                                <Component Id="cmp022B66C05DEF11B72F5542F7A563B670" Guid="{13CE3EBF-5709-4E53-A16E-AD8D594269B6}">
                                    <File Id="fil359A08138CF8104E01BEDDFBCF601539" KeyPath="yes" Source="$(var.BasePath)\wwwroot\css\open-iconic\font\fonts\open-iconic.otf" />
                                </Component>
                                <Component Id="cmp0F72C70E7993CC0B3E9FF70ED40066D9" Guid="{50A1B8A9-FC5F-4DBF-A5B9-23BF36B86461}">
                                    <File Id="fil58F851EE53BB2984EF8AD39C75D6ED2B" KeyPath="yes" Source="$(var.BasePath)\wwwroot\css\open-iconic\font\fonts\open-iconic.svg" />
                                </Component>
                                <Component Id="cmpFA0036474721DE0D4163E05499F39951" Guid="{48316E0E-AFCD-42C8-81DB-2BFA5B78098D}">
                                    <File Id="filE8C22BD61F80DDEF89A090F2D3088910" KeyPath="yes" Source="$(var.BasePath)\wwwroot\css\open-iconic\font\fonts\open-iconic.ttf" />
                                </Component>
                                <Component Id="cmpB5AF9E63913432C07629EC20330320A3" Guid="{AA08AEF0-1074-4798-A594-3D2336A888D0}">
                                    <File Id="fil6C6239428714D4469CE9DC4AC970572B" KeyPath="yes" Source="$(var.BasePath)\wwwroot\css\open-iconic\font\fonts\open-iconic.woff" />
                                </Component>
                            </Directory>
                        </Directory>
                    </Directory>
                </Directory>
                <Directory Id="dir2456A1A1C6D6186A96473C7CCDFCB992" Name="_framework">
                    <Component Id="cmp9D66267AB1CAF7A98DFC42947DC635D4" Guid="{5001E34B-2EE7-405B-AB2E-3796E0A80C0F}">
                        <File Id="filB44D114325A011114C21CBE4A300CB0A" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\blazor.boot.json" />
                    </Component>
                    <Component Id="cmpCD4F94EB73F3962B42308170454B4366" Guid="{94C7954D-AE32-4F74-B486-EDED35A5DCD9}">
                        <File Id="fil95D8DA1D1C8714B25ACFD17A854A6556" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\blazor.boot.json.br" />
                    </Component>
                    <Component Id="cmp6D7DA841FD268735AFB1026BA6AE24A3" Guid="{2693A4A8-6008-41AD-A7F7-1BA66EBF6C79}">
                        <File Id="filE6753DF182773CBE5CB34EFF14F104A1" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\blazor.boot.json.gz" />
                    </Component>
                    <Component Id="cmp08111D788677D8B8150650EE58FB5962" Guid="{CEDA9984-84D1-451F-ABDE-626A8C59F7C5}">
                        <File Id="fil91C23D13B8DAFF05EBEB8392CE68B52A" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\blazor.webassembly.js" />
                    </Component>
                    <Component Id="cmp5A46DA40AED3B5E10AF9751BA0029C2C" Guid="{2D3F6029-21F3-4303-87BF-57533CA6DD32}">
                        <File Id="fil8B39D85752BD54316DA226C75F3327CD" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\blazor.webassembly.js.br" />
                    </Component>
                    <Component Id="cmp6A6C2351815759B4DB8982A7741D0ABA" Guid="{9DFD3F7F-C3B3-467F-B20A-BC93AB02E79F}">
                        <File Id="fil19B6F698DFFF12083A98F5D787FD0C27" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\blazor.webassembly.js.gz" />
                    </Component>
                    <Component Id="cmp82623C6CA3D1FE2B38C69748720D46CB" Guid="{F1498C70-7946-48C6-B0B5-D0D9AAE667F9}">
                        <File Id="fil08BC13C8E449CA8F8A63459958299CC2" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\BlazorAppForInstaller.Client.dll" />
                    </Component>
                    <Component Id="cmp2EAADFED8A771ED40D36F4261011FC42" Guid="{CBB22CE6-A9AB-4AAA-8C7A-8DF7E75097C5}">
                        <File Id="fil8BFAA357E90079ABABE1BCF4BA473A95" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\BlazorAppForInstaller.Client.dll.br" />
                    </Component>
                    <Component Id="cmp0C35E5441CB1AEE868B0841FC2B3727D" Guid="{88347808-0D45-4D45-8481-38208053A58F}">
                        <File Id="filA93D1C70A69655AA4C51B3783DEF7929" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\BlazorAppForInstaller.Client.dll.gz" />
                    </Component>
                    <Component Id="cmpF7B971FD5EDDB748109439252E62DBB2" Guid="{27F9F764-1382-4933-9E5A-5DD08B7D16C0}">
                        <File Id="filEBF0235031F25983E7C1A9288636FA06" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\BlazorAppForInstaller.Client.pdb.gz" />
                    </Component>
                    <Component Id="cmp1A38450971536177F12598D9DA69460B" Guid="{A75C8817-B1F6-4DA9-9900-B40F240C5DC1}">
                        <File Id="filBB8B83E5A719B33BDFBE76BD743CCF89" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\BlazorAppForInstaller.Shared.dll" />
                    </Component>
                    <Component Id="cmpB3C98B1AF19712A5A4C90299621D5AA3" Guid="{96975A6F-A077-4100-B12E-1DD3399CCB5A}">
                        <File Id="filEB014231B74E00067909368905F30EE7" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\BlazorAppForInstaller.Shared.dll.br" />
                    </Component>
                    <Component Id="cmpB532E6FD17B9FD1DDEF930DAB1CDCC8C" Guid="{C682083C-EBDE-4A5F-B609-AAED3ADD024F}">
                        <File Id="fil5E81E1CB0A6DE77CBC8370A61E06C38B" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\BlazorAppForInstaller.Shared.dll.gz" />
                    </Component>
                    <Component Id="cmp930FCEACB08C3F828E26B2B4AAAD3B58" Guid="{F87DB6C4-DE5E-4274-8DC5-E93C92AE35BB}">
                        <File Id="filF270CDA0AFA589A3714231A594BCD5FB" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\BlazorAppForInstaller.Shared.pdb.gz" />
                    </Component>
                    <Component Id="cmp94D35364CD546AECFF1FD3E16E7705BC" Guid="{2E38C9A8-06D4-4A9E-A090-C47083799C8B}">
                        <File Id="fil0170682B3A5D149D65261C93955427C3" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\dotnet.6.0.4.33aaebng0v.js" />
                    </Component>
                    <Component Id="cmpEEB478F290FD8E012F256864DA59B87A" Guid="{9D6ADBA3-2C2B-40A3-AD1C-A622C796B35B}">
                        <File Id="fil4BFFAB0897DDFF6616372F10D397F4C5" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\dotnet.6.0.4.33aaebng0v.js.br" />
                    </Component>
                    <Component Id="cmpABBCFC94814B14153BE6A9A7989C2A0A" Guid="{921EBFCE-279F-4146-A223-6AC7A86B82B3}">
                        <File Id="filC837371EBEBB4A85095F62968F246518" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\dotnet.6.0.4.33aaebng0v.js.gz" />
                    </Component>
                    <Component Id="cmpF242BF7465335E363684D1995205E1BD" Guid="{7238E4CE-E418-4603-AB1F-2C5064257911}">
                        <File Id="fil100971A9827D4A995FD58C69132C7F78" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\dotnet.timezones.blat" />
                    </Component>
                    <Component Id="cmp02E6C2F0AD10D0478D86BE37452B0914" Guid="{256ED6AB-05AB-4201-9B25-CC374E7AC3E2}">
                        <File Id="fil349A7A48CB5B0B3B0DBE9F8FDB0E73A3" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\dotnet.timezones.blat.br" />
                    </Component>
                    <Component Id="cmp4A0D7430E5062327165BBC0627BB2583" Guid="{979FCAC9-D8EE-44AB-9B0C-850E5D1BEBAF}">
                        <File Id="fil0886807D84E5ADBFAE7CA9BEC8FFA851" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\dotnet.timezones.blat.gz" />
                    </Component>
                    <Component Id="cmp39219EB53A18F9EF8C1D9E629B44B00E" Guid="{22B4717D-5557-4F1B-971F-23FE4E288EA6}">
                        <File Id="fil68C7BC2EE4C13DECCA9E6FB9D7C824A9" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\dotnet.wasm" />
                    </Component>
                    <Component Id="cmpA1E64C6DD02D1B8D3365CDF712DE7740" Guid="{B626E6DB-2D54-4452-A1A4-6F3E26C040CB}">
                        <File Id="fil2A596AD93D719FC8D9587E4071ADD444" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\dotnet.wasm.br" />
                    </Component>
                    <Component Id="cmp2F00835F6AB457CB0746B0CF23BBABC4" Guid="{B58C9A4C-87F2-4854-AAC7-6D2872E24C9E}">
                        <File Id="fil9EFAF48DDA876292454A09D0ABB854E5" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\dotnet.wasm.gz" />
                    </Component>
                    <Component Id="cmp728A6879EC0D4538CF0D9A610CDB29AB" Guid="{73825831-1C6F-4309-BD38-DA71EB9D08C7}">
                        <File Id="filA6E451B0F223EACAE5E0D5C4634C5F3D" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\icudt.dat" />
                    </Component>
                    <Component Id="cmpCF6F10CA4A3650B98898E76461DBDB47" Guid="{3116E39D-5666-4B49-A07C-C3DFEB00431E}">
                        <File Id="filD2CE1A50BBA0A22996BE87C71FB6B412" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\icudt.dat.br" />
                    </Component>
                    <Component Id="cmp512FC92BCC546D0A442E2A50E378BA60" Guid="{D815DB8F-3108-4B6B-8233-C0E9DB54359D}">
                        <File Id="fil18707646D8908FCB093B7109B82D706C" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\icudt.dat.gz" />
                    </Component>
                    <Component Id="cmpA8FCAF75866687FC4A4693E426913FBA" Guid="{EBBDA200-5E60-41F6-8A34-8237385C2BE1}">
                        <File Id="fil9BDA85D8F75E1651CAC2432153EB4836" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\icudt_CJK.dat" />
                    </Component>
                    <Component Id="cmp747FF5C347AA12FFF91DF70F289BC1F7" Guid="{0F1FF7D6-ECFF-4321-9AD2-5B7B078BCE6D}">
                        <File Id="filCD2D30AC48BC4F5A8FE9379F4D69A5EF" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\icudt_CJK.dat.br" />
                    </Component>
                    <Component Id="cmpDEF19AE67395660D7A04537C771DEAEA" Guid="{E02B6461-7A78-4680-8E25-5992D1ADAC3C}">
                        <File Id="fil1D562F69200614371432FB36A61CF636" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\icudt_CJK.dat.gz" />
                    </Component>
                    <Component Id="cmp286486FA354377E5944B31BCB5E1BD86" Guid="{38D93EA2-EDE3-49FB-977A-B8AC290C63BF}">
                        <File Id="filC6F93228041B4AC1C5D2CB9DAD61425C" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\icudt_EFIGS.dat" />
                    </Component>
                    <Component Id="cmpDA5F2E45468ACB6957DF118202F57CBA" Guid="{2877D2BE-A1D7-46B8-AE47-53D9B447FA9D}">
                        <File Id="filA7C7633C832FDE23C3A3D543BE4E0117" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\icudt_EFIGS.dat.br" />
                    </Component>
                    <Component Id="cmp329238427D6DFA82B9DE0EC84FAA175F" Guid="{19E13614-89FD-4B1F-BC3F-4D9FB4A82391}">
                        <File Id="fil85E8885AF7B63E77FC30F33EA7464A10" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\icudt_EFIGS.dat.gz" />
                    </Component>
                    <Component Id="cmp006F8D28BA0AFE320C8E136D5C68A581" Guid="{B03BEBED-7876-4B59-A69A-07C2B09D0F56}">
                        <File Id="fil308F3F6ED362594B77EF7CE88BCCB855" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\icudt_no_CJK.dat" />
                    </Component>
                    <Component Id="cmp538D88FA41B7B0483DDF492891D5D684" Guid="{AE37820A-AD7E-4A3B-85B5-5C713E0F701C}">
                        <File Id="fil164352E303F8D7119412937E644F3D90" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\icudt_no_CJK.dat.br" />
                    </Component>
                    <Component Id="cmpF9E68B4BB97E17771AA221E83025CF38" Guid="{6A00E0B1-C08D-493B-A5FF-01001D31ABC0}">
                        <File Id="fil74816C0820AAF70E089B169C5EFB8E03" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\icudt_no_CJK.dat.gz" />
                    </Component>
                    <Component Id="cmpA38DF32DEFA15EAB22A6AF80CC0DBA93" Guid="{92746487-239F-4375-A057-E73C72E0CBB3}">
                        <File Id="fil6A69DAD1824C6F4ADEEB75886F45C215" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.AspNetCore.Components.dll" />
                    </Component>
                    <Component Id="cmp7A14C98BD98024E214134EE58D8A2A0D" Guid="{75D3F763-C971-439B-9659-73B0A2E3921A}">
                        <File Id="fil40B121415F82041273E4F86F31649747" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.AspNetCore.Components.dll.br" />
                    </Component>
                    <Component Id="cmpFB1DAD1066930B4BCF63BD47478DA044" Guid="{EA42F28D-BB0F-4C93-AC68-E7DC429407D2}">
                        <File Id="fil4C568CE1D72145CE5D718E8A0D713E94" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.AspNetCore.Components.dll.gz" />
                    </Component>
                    <Component Id="cmpD5C2C4A360A21B8188754FC87E3531E0" Guid="{6FBD58DA-054C-4E9F-B2E4-5BCBBE4A096D}">
                        <File Id="fil20852D9320634269944588FC0AB30EF4" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.AspNetCore.Components.Web.dll" />
                    </Component>
                    <Component Id="cmp971F14265094A43D81FE6F2B7D1AF6B7" Guid="{9D277B49-4260-4A16-8DC7-BB1507080255}">
                        <File Id="fil4D323C615D70E0296DE05A39ABCF2483" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.AspNetCore.Components.Web.dll.br" />
                    </Component>
                    <Component Id="cmp0326270DDC7B6B2E7294E885AF295E3A" Guid="{E678F79C-3DF4-46A4-AF1F-31479BD0735E}">
                        <File Id="fil8A47DF30080F4F85E90D8AEA0D7C68AE" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.AspNetCore.Components.Web.dll.gz" />
                    </Component>
                    <Component Id="cmp514A78E3D9A3A1B0381C2609914F3FCD" Guid="{0A8FC9D2-72EE-4D7C-A4EE-9BE0F95C367E}">
                        <File Id="fil802D2750CD020A3D5E78C40AF27FCE7E" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.AspNetCore.Components.WebAssembly.dll" />
                    </Component>
                    <Component Id="cmp3B994E9EC7D69DA30E3341DDCA1C2E35" Guid="{C6668F6E-6A32-48D5-93DF-C808FFF25500}">
                        <File Id="filFFAD2F1CF56AFA39BB66C4F6E53F5D7C" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.AspNetCore.Components.WebAssembly.dll.br" />
                    </Component>
                    <Component Id="cmp8648F3FB6E0C32E344C77586438BA083" Guid="{50B5A6DB-AABA-45D9-9A8A-F1970F04DF92}">
                        <File Id="fil658F0AC6351BC749808CDEBEDCD9E184" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.AspNetCore.Components.WebAssembly.dll.gz" />
                    </Component>
                    <Component Id="cmpA160DA65B8DFE4CF4F6754B9B315896E" Guid="{39112D1E-BF00-4F2B-BE9C-233E177B3CC6}">
                        <File Id="fil009E11A5AB23FA4EAEC7ED47EB533CDD" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Configuration.Abstractions.dll" />
                    </Component>
                    <Component Id="cmp4242E026351F6B91ED373820F5BA7E70" Guid="{BD35E2A6-3DE8-4E26-9FEE-9FEF1D2CE7D7}">
                        <File Id="filA06F61D6AE665C6ACBA435342CFC6210" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Configuration.Abstractions.dll.br" />
                    </Component>
                    <Component Id="cmp42CC4971550CD97B0B702F1471CB4C72" Guid="{108B946B-835F-4724-8286-A79019524C9B}">
                        <File Id="fil34237AA456807B011EED94EEC76855E5" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Configuration.Abstractions.dll.gz" />
                    </Component>
                    <Component Id="cmpF91962248A2205ABCF3B6BD33C74BAF4" Guid="{98E07B5D-447B-4731-9947-A6E6C7010E56}">
                        <File Id="fil8D0B84ED97BAF65B0ACE402589060BB0" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Configuration.dll" />
                    </Component>
                    <Component Id="cmp5DEDEDAD272B08B21352520216DB4781" Guid="{A268F034-777A-40D8-8AE7-86F41E5002A2}">
                        <File Id="filD823E906EA5BDACAD60F824A553714AE" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Configuration.dll.br" />
                    </Component>
                    <Component Id="cmp9173B268855879B81EDE2F0FD17367A7" Guid="{A1BE20EE-4DB9-458A-8D4F-EAA9D4FA098F}">
                        <File Id="fil1CACF1BC049F6E4239657CF6557D1070" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Configuration.dll.gz" />
                    </Component>
                    <Component Id="cmp5F4A3E3B2CBE10DA3D1BE6856D377E48" Guid="{D6EE7763-CA19-4AD8-AAB6-2579C4B1C214}">
                        <File Id="fil1F782C0520BFAD02930D3D41F1B1AC17" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Configuration.Json.dll" />
                    </Component>
                    <Component Id="cmpAEAABAB05E5E18C6E5D596B5134B11AA" Guid="{41A05EF2-9B05-47EE-ABA9-5D6FF05FE9AF}">
                        <File Id="fil1EA5135DAEC4BCA7F0393E23CEE978B0" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Configuration.Json.dll.br" />
                    </Component>
                    <Component Id="cmpB7F61D4C72FC6E25B4BD2D7C406028AF" Guid="{C650C27C-854B-4357-898A-B9BD5483A508}">
                        <File Id="filA7E3A736B61DC726180AD1A11AE061BC" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Configuration.Json.dll.gz" />
                    </Component>
                    <Component Id="cmpF7B0EE03C7D98B064308BA96508AE479" Guid="{29C33D15-B96B-47C0-8DAF-B95D330F7FF5}">
                        <File Id="filAC0A7B0EDFBB7791CBCAA7ABF495C580" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.DependencyInjection.Abstractions.dll" />
                    </Component>
                    <Component Id="cmp86A1AADE6BF473BDAE88C6F24BCCA966" Guid="{48EE1B2B-54E1-468E-8EBD-6FB26F2B3919}">
                        <File Id="filD07CE14E098E28AF0A5FD83A0C257049" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.DependencyInjection.Abstractions.dll.br" />
                    </Component>
                    <Component Id="cmp975438FFB4C20A8535CA709CDD345C48" Guid="{91C733F3-782D-4219-9A92-43BBEF0BA3B3}">
                        <File Id="fil606F02CF9E1797C7B7F108712DC24500" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.DependencyInjection.Abstractions.dll.gz" />
                    </Component>
                    <Component Id="cmpAE73F552B8F7B3A26A0C4D716BDDB8B8" Guid="{D1A9B445-04EE-4611-8928-DA4AC13AAF6C}">
                        <File Id="fil15FEEF6525A9FC4EF41735F78B121AF3" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.DependencyInjection.dll" />
                    </Component>
                    <Component Id="cmp7858B731FC612FE7E07A6122BFDBA4D8" Guid="{A1FBA75E-A354-4DE8-BB97-F8FEB0AC4A97}">
                        <File Id="filEA94D6EFC482DE959D14E73DEF2F9799" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.DependencyInjection.dll.br" />
                    </Component>
                    <Component Id="cmp3CD942B25C15D4F3B3B8BA16662EFCEC" Guid="{86F17A53-55B0-437B-A9BE-6A73951D1B2F}">
                        <File Id="fil0A304EF7F79CF49A169E5A885F189277" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.DependencyInjection.dll.gz" />
                    </Component>
                    <Component Id="cmp7BC7B696CC9C4EC000AAB5D52588B1BC" Guid="{469F6FDB-2C12-4404-96FC-C2C1C2DA989F}">
                        <File Id="filC4A48A09556A780EB3CFC1A33F965EFE" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Logging.Abstractions.dll" />
                    </Component>
                    <Component Id="cmp707551BC0DBA68C6D49E4ED09CC3FE90" Guid="{3E54DD8E-C58E-406E-BA57-2A269E781CDA}">
                        <File Id="filDBB61B02BDFF3C6843B1B468A559ADA9" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Logging.Abstractions.dll.br" />
                    </Component>
                    <Component Id="cmp515E95EEE930BE8B288A5B6D95C4F6B6" Guid="{245D47D0-F8E5-4623-8C58-D7A61C846FF4}">
                        <File Id="fil7FD0B4E3B7BCF3AA9C6C0E29EACDA2CD" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Logging.Abstractions.dll.gz" />
                    </Component>
                    <Component Id="cmpE060C6A31FDC9AA148DBE1CD795BDD87" Guid="{FE7403C6-356B-4185-9E9D-4D97822E63B4}">
                        <File Id="fil5605734554345F4F36AA24D3C64053AF" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Logging.dll" />
                    </Component>
                    <Component Id="cmp51F55DD4FA3ECC6EC277B603BAE77E4B" Guid="{EDDB08FF-FA51-4EB9-A38E-81CAC6F6E0F0}">
                        <File Id="fil40167D8C2CE51BF97351AF5BA196B067" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Logging.dll.br" />
                    </Component>
                    <Component Id="cmp09275652FE8A5CC3B05F9F04F4ACDAB8" Guid="{4CA48B37-DA80-46E2-8791-932F9BD2B90E}">
                        <File Id="fil7E1DCF5917210F2713343978FEAFC18C" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Logging.dll.gz" />
                    </Component>
                    <Component Id="cmp4C12430D81FCE43486C72C98ACA22DE4" Guid="{4E35A9F2-29C9-4898-BA11-F97B7F2468A1}">
                        <File Id="fil497BDFF56C9C493B4EA3BB05CB84E6C4" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Options.dll" />
                    </Component>
                    <Component Id="cmpAF9DE5022005A570309CDC608D8817FE" Guid="{D7F8D688-C979-4049-8D0D-B7902ACD1E9B}">
                        <File Id="filEDEFBD7086806983D3A9F7B302294874" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Options.dll.br" />
                    </Component>
                    <Component Id="cmp864779AFDF069BB096C3D55EB7E67D17" Guid="{5F1E29A3-6ED6-4339-93CE-E008A48E0167}">
                        <File Id="fil95DA4561466E116EBCFFB2304CE45E3D" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Options.dll.gz" />
                    </Component>
                    <Component Id="cmpBDCF4227A3F14BFD217701F4E1AEF581" Guid="{1D9DE43C-B81C-4166-97E4-BB869393E51C}">
                        <File Id="filFCEA26229C64F5B0DDC4F300E527003B" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Primitives.dll" />
                    </Component>
                    <Component Id="cmp8C2B056893FC9B4F917F1D60A86CAF46" Guid="{F5C200A4-4B00-4BC9-ADF0-816528383EE2}">
                        <File Id="filA5FEC50FDD462EFE465ED50197DA27AC" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Primitives.dll.br" />
                    </Component>
                    <Component Id="cmp5205763847DAE3B1F0E9A557ECEA0294" Guid="{8D771669-627C-47A5-A0B6-83148104C4F2}">
                        <File Id="fil6FE0C53D273C04D664103B017EB6B7FC" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.Extensions.Primitives.dll.gz" />
                    </Component>
                    <Component Id="cmpE22F274295C3DEF43785B45EC2A93623" Guid="{9F311DB3-4571-4CB6-86C2-AD10F536A480}">
                        <File Id="fil9CF7F6D0082CC00831BCB79B512F6DDC" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.JSInterop.dll" />
                    </Component>
                    <Component Id="cmpB8A2E71C8CF36DE8D8F53A1D8C90371C" Guid="{1AA84CBE-D211-45D4-9F58-76554544CC42}">
                        <File Id="fil343FB5CD812AFA562BF31FD0BDC5BCEE" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.JSInterop.dll.br" />
                    </Component>
                    <Component Id="cmp73A0603CACC8FD37AE5400E72FB390B4" Guid="{F4869EBE-CA6E-459B-BE6B-6F64E4E98C60}">
                        <File Id="fil8A998F649F697B54B836C9E31DFEFD27" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.JSInterop.dll.gz" />
                    </Component>
                    <Component Id="cmp2F2ED6725809828FFA8AF2B1F4793156" Guid="{5E0F9CD9-A13A-4F21-9B81-F4232A460F08}">
                        <File Id="fil2A6F7DDF91413905561875B8A447A547" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.JSInterop.WebAssembly.dll" />
                    </Component>
                    <Component Id="cmpDA5844562D73C6F04F932F5314A77A39" Guid="{51C97F73-DD58-4529-B174-E4FA52FA7AA9}">
                        <File Id="fil0F726A6415D2ADD8D2559118F8727F5B" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.JSInterop.WebAssembly.dll.br" />
                    </Component>
                    <Component Id="cmp7C9F2443CAE1F55295CD79951408C721" Guid="{620AC919-B5C7-47CA-9328-A997EF2A6253}">
                        <File Id="fil71F4B87F19AEAFF7939C1EE93FE6FE73" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\Microsoft.JSInterop.WebAssembly.dll.gz" />
                    </Component>
                    <Component Id="cmpA65D953E5A54247042B256470D47D4AB" Guid="{F053B0E4-C996-4310-8252-897F53F3E1B8}">
                        <File Id="fil8895E72799380F4E05CAEBCD685DDBE2" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Collections.Concurrent.dll" />
                    </Component>
                    <Component Id="cmp51F02589BA588D783C3C603656194CC7" Guid="{7DBE3773-D328-4905-AEB0-55547E987881}">
                        <File Id="fil004F6DABDDB1C96CE27C8F35F0DC9DDA" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Collections.Concurrent.dll.br" />
                    </Component>
                    <Component Id="cmp5937FF9962810B779AC2D3AB0E1FFA31" Guid="{B4E3EFBD-D454-427C-89CF-4992325069B0}">
                        <File Id="filBD9E064AE6BA6531330CC8A72F2D68BE" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Collections.Concurrent.dll.gz" />
                    </Component>
                    <Component Id="cmpB4F75E93D852D00850CC0545706516AC" Guid="{AFB6171F-EB34-4887-B8A6-AEB05E9DBDDB}">
                        <File Id="fil72DFEAD849270C7487E1922671555A98" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Collections.dll" />
                    </Component>
                    <Component Id="cmpC482BD0E23AD6B0866F0EC3B3EE21912" Guid="{96712566-72E8-4398-9281-BDC6920958B1}">
                        <File Id="fil9DD14B36011AD1AED77223FE87E184FC" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Collections.dll.br" />
                    </Component>
                    <Component Id="cmp20D34FC7203469574D5B870FBFDB6F7F" Guid="{12C35146-B5E7-4160-8F7D-ABAC85ECC51A}">
                        <File Id="filBB29036EFDD1D8D5AA5DC924CD208D5D" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Collections.dll.gz" />
                    </Component>
                    <Component Id="cmpA826E1BF780AE0933557676389100061" Guid="{FEB1C65D-1E53-4E89-BAD3-BE9BDC8B0B8E}">
                        <File Id="filAFDFA52206BB9423B6CE2C685284CA99" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.ComponentModel.dll" />
                    </Component>
                    <Component Id="cmp2A2D126124E8909219DB6B0BD3DB7281" Guid="{7B41DDFB-6A7D-4B79-B200-A4DDAACD6A22}">
                        <File Id="fil271CA6B703F5070B21C12F8EADEAB1BF" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.ComponentModel.dll.br" />
                    </Component>
                    <Component Id="cmp48F0DEF6E07C958C489DB5F099A47D02" Guid="{5C0DAE60-1552-4F6A-B845-9B509E04C91C}">
                        <File Id="filB43BEEE84D76BE6B8E121624D1937EB4" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.ComponentModel.dll.gz" />
                    </Component>
                    <Component Id="cmpE51D0DCA6EE2771B65D0DB930DA0F422" Guid="{7E2CCB1F-0AB1-438C-A2D0-CC29E22270D8}">
                        <File Id="fil25D4C6054723DCF53741AEA2FCE1D13B" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Memory.dll" />
                    </Component>
                    <Component Id="cmp16DCE2C779691329ACBD41A17893807C" Guid="{1BF83602-DC3E-46B8-9B18-E0D8878B4413}">
                        <File Id="filBA4C797C8626633866C4D2E2FE570242" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Memory.dll.br" />
                    </Component>
                    <Component Id="cmp607A37F44559C1B9663107B3C5780416" Guid="{23343BC9-BF41-4E66-B3F6-A368A8889DB5}">
                        <File Id="filBFEDF80BCA685FDC664033CA845F4233" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Memory.dll.gz" />
                    </Component>
                    <Component Id="cmp3750CA84737F30C6A133B736D82311DC" Guid="{6CBA8DC9-B192-42C3-8D31-AD9A026C1E94}">
                        <File Id="filFE5E821A8E08C92D63E707F7DAB9B3A6" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Net.Http.dll" />
                    </Component>
                    <Component Id="cmp5F48A2E610A688238A2DF46678BFC4DA" Guid="{38C8A848-63A6-48B1-BC49-248952C3CA5A}">
                        <File Id="fil6A576146A10F514A4FEE0D9A2F62E66A" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Net.Http.dll.br" />
                    </Component>
                    <Component Id="cmp333F8CFB28D84B1BFBCFD0207AB4C8DC" Guid="{3AD9E240-3E6D-4E09-B91E-A8E471866767}">
                        <File Id="fil5C3E404B87A4A624EA1008033586135B" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Net.Http.dll.gz" />
                    </Component>
                    <Component Id="cmpED48E5DDB3EBB7C71EDACF54D349688E" Guid="{6432BBFD-BF55-4F25-BD89-746508129B88}">
                        <File Id="fil945264EEB7D05962944632DB40D103F6" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Net.Http.Json.dll" />
                    </Component>
                    <Component Id="cmpFA624270AF509809FE8CD8C49FA60779" Guid="{D65CACAF-3BED-4591-B80B-AF9CA572F470}">
                        <File Id="fil48DFB166E1B2D0E5F602E450BDA268D5" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Net.Http.Json.dll.br" />
                    </Component>
                    <Component Id="cmp50C00207A15C4550FE7A85241C74BBE8" Guid="{2AD2A4A1-7007-4413-AEDB-2590D7E520B0}">
                        <File Id="fil6585BFE45253B14831A430FDDECF04C7" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Net.Http.Json.dll.gz" />
                    </Component>
                    <Component Id="cmp56887909ACB3B8F6402B40E26751C3B3" Guid="{F7F53191-F371-46DA-B469-04D6D73ADFDF}">
                        <File Id="filE0FF1A9872F99F1E4D32910E53C186C0" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Net.Primitives.dll" />
                    </Component>
                    <Component Id="cmp0976629DB2D3387B7524A1EA5BB9828A" Guid="{A1D24AE4-2A92-42F3-927A-C7F6F0FA9BDA}">
                        <File Id="fil00CC944E233AB04D3545A0E244417382" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Net.Primitives.dll.br" />
                    </Component>
                    <Component Id="cmp9BEE2BBA2E625E10ACE5D38F9CE29E25" Guid="{AC479C09-1430-473B-B535-353378D3E807}">
                        <File Id="fil7EA368F875D5AAD4C64F77E41A6E23AF" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Net.Primitives.dll.gz" />
                    </Component>
                    <Component Id="cmp1740817C651EE407F3A14689504EEF0B" Guid="{5F40E782-D9F5-4094-BF3A-D96BA646519A}">
                        <File Id="fil92050D8BEB3B82F62508D2473289059B" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Private.CoreLib.dll" />
                    </Component>
                    <Component Id="cmpB1F2210BCA59E771BFE567C4B70223E3" Guid="{9F599BC5-AC3F-4708-8EEE-33AD7CF44D9F}">
                        <File Id="filFC0EA5B332077F9C3AD1339464605983" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Private.CoreLib.dll.br" />
                    </Component>
                    <Component Id="cmpA098BA5EC2A20A12327DB7E9D1560C36" Guid="{B46F7ACB-8D2F-48E4-8329-4DB270626DF5}">
                        <File Id="filF20866D9620DEA24F42C6BC3533B0DD0" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Private.CoreLib.dll.gz" />
                    </Component>
                    <Component Id="cmp4DBC5ACFDAEC1C4E3CD7EF1AC171CDD4" Guid="{B6B28027-F77B-4BA9-82BE-99F5D12BD14A}">
                        <File Id="fil84342B01143909094AC4F27D453CCF22" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Private.Runtime.InteropServices.JavaScript.dll" />
                    </Component>
                    <Component Id="cmp1173314C87D3A1C6669E796D63BA0B5D" Guid="{9B209BED-B524-4AD2-843B-66C0358E78C9}">
                        <File Id="fil3ABC05F2D210D029B9BC94BE2FC22A9C" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Private.Runtime.InteropServices.JavaScript.dll.br" />
                    </Component>
                    <Component Id="cmp0A248A654EDFBDA44693AADCAC9DD461" Guid="{922B4040-685C-460D-BF3F-28AA61DD8BFC}">
                        <File Id="fil9FB6E89FC7B2CCB51474A12BFA99B4FC" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Private.Runtime.InteropServices.JavaScript.dll.gz" />
                    </Component>
                    <Component Id="cmp9DB136D1B06E1CFF3226F8FF247FA400" Guid="{D7D96DAF-DF94-42AA-866D-7283605EAD93}">
                        <File Id="fil112BD196CC1B5B4AD4D7D583398FE147" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Private.Uri.dll" />
                    </Component>
                    <Component Id="cmpDCFCF9BD3503D6340AA0A2B21FE7FBCC" Guid="{ED5FEA3F-00F4-41B5-B97A-402ACCE765C8}">
                        <File Id="filE2A25AFD13442571FE641F364E470893" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Private.Uri.dll.br" />
                    </Component>
                    <Component Id="cmpD1D9EEDAFC075B3BC32EE7298288086F" Guid="{E14DA94F-CC7D-46E7-A992-B8A75A49E432}">
                        <File Id="fil9B542E73B61E1A0DB2E6354A641F6CEB" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Private.Uri.dll.gz" />
                    </Component>
                    <Component Id="cmp740321EAD6FA852678D49E02C9131145" Guid="{12F99079-3F99-4690-BCB8-431A0CC37716}">
                        <File Id="fil64814F821C696DC6C9496821E23668F2" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Runtime.CompilerServices.Unsafe.dll" />
                    </Component>
                    <Component Id="cmp743C84704C46065CC2390782C88647FE" Guid="{44B7F53C-993A-40B0-A8E5-7D38720E4111}">
                        <File Id="filC26B779E0B33BAFC1A30D48B1A870ED8" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Runtime.CompilerServices.Unsafe.dll.br" />
                    </Component>
                    <Component Id="cmpC370C60937565F7FB65302F95A8C1FF0" Guid="{EF593AFB-4158-479E-AAC2-192AC7F57579}">
                        <File Id="fil19E6EEB3BDAF719BF0133E45D88A03DF" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Runtime.CompilerServices.Unsafe.dll.gz" />
                    </Component>
                    <Component Id="cmpE9537DAAFB13ACF42382B5F39E041AAE" Guid="{F2484F22-5F1F-4490-B163-5D80D8822135}">
                        <File Id="filB923ECB75321ADB1F2B711305B6AB357" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Runtime.dll" />
                    </Component>
                    <Component Id="cmp3AE669088A014BAB8C199390E02DB7E7" Guid="{E5B2977C-1B3E-4CF2-876C-DAC9579C9330}">
                        <File Id="filF4DCDF75398370DD75D51E1510602BFC" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Runtime.dll.br" />
                    </Component>
                    <Component Id="cmpAB7158EA13F736C1E0451D0807BE4947" Guid="{AC9943C5-30E1-4ED4-B75C-F0B067C1A090}">
                        <File Id="filD4698EA1B34887AE694A74475593E3E3" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Runtime.dll.gz" />
                    </Component>
                    <Component Id="cmpBE312FE3FB6A6BDDAB0FE75F1EC0F480" Guid="{04293042-0055-4A8E-A2E8-DE9374B4758A}">
                        <File Id="fil18CECB88CBBA124C417F9726260D1B30" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Text.Encodings.Web.dll" />
                    </Component>
                    <Component Id="cmp9D0A4D86ADBE049A6CD726A4C5FD96EE" Guid="{DED6A3FF-479E-45E9-BA1C-1D48FEAD61FE}">
                        <File Id="filE932324B082B8169CC0334B9B68E7346" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Text.Encodings.Web.dll.br" />
                    </Component>
                    <Component Id="cmp6C9D44905338F4A80BCF436FADD3333E" Guid="{7482DA68-E977-4B51-BD6B-44DE843BFBF6}">
                        <File Id="fil2CD4D93571823B42747D1E81549C12DA" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Text.Encodings.Web.dll.gz" />
                    </Component>
                    <Component Id="cmpED3B8CFD2C58E76550E55BB568433B01" Guid="{77F7D092-BAFF-4368-BD35-FBB8D7E4A676}">
                        <File Id="fil6242EB6396FCEB42E682BC2B7EB5ECAD" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Text.Json.dll" />
                    </Component>
                    <Component Id="cmpBA0FF53077EEA56D55F8AB637925580B" Guid="{9010AEC8-0EB3-4DA4-A69C-16CCA4CA82FA}">
                        <File Id="fil1D0FC0B73348482750C57247305BA66E" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Text.Json.dll.br" />
                    </Component>
                    <Component Id="cmp63CB25923717C691B1A5EA40B6C111F0" Guid="{A570FD8B-480D-4429-8EF9-90DB914E9A08}">
                        <File Id="filA19C569DA0C381BF3584866DD2BAA824" KeyPath="yes" Source="$(var.BasePath)\wwwroot\_framework\System.Text.Json.dll.gz" />
                    </Component>
                </Directory>
            </Directory>
        </DirectoryRef>
    </Fragment>
    <Fragment>
        <ComponentGroup Id="PublishedComponents">
            <ComponentRef Id="cmpA0863526952F7834E7C922F065E4C8A8" />
            <ComponentRef Id="cmpF82FCA80BBAF44D285C97F10993DEEE6" />
            <ComponentRef Id="cmp80A32365AE3ACFE27BDD385AE91DCE74" />
            <ComponentRef Id="cmpF69BDBE9F42451436A0B8C022F6D4636" />
            <ComponentRef Id="cmpFD59DF07063AC308C40670A4B81A9B57" />
            <ComponentRef Id="cmpECDF00A9B659260C50885BEEADBCABC0" />
            <ComponentRef Id="cmpE351BCDC42EF493685CEF4080E08E51E" />
            <ComponentRef Id="cmp651C3999A00B5D89ACAE2D3A9BE7F91D" />
            <ComponentRef Id="cmpBCBFD41B8B964007BA9BF340925C6493" />
            <ComponentRef Id="cmp9A7CD58BE639399F7BDAA987492B6E65" />
            <ComponentRef Id="cmpB818026BC106A80C4FD6E90BF8F06CDA" />
            <ComponentRef Id="cmp2F0A313AE6306F9CE5E760AF214DC789" />
            <ComponentRef Id="cmp6D6CC90C40E2F632C9128346BA7F188F" />
            <ComponentRef Id="cmpA76C6CFFA9DCB201D0EEDB226B0B9E25" />
            <ComponentRef Id="cmp17959BADF0C2D7B7AB4867F09DA031B8" />
            <ComponentRef Id="cmpDF4C205418A6D7FE6FEA71F3B8998FAC" />
            <ComponentRef Id="cmpDA8B0BBD16E996DE615D6861DBA6442F" />
            <ComponentRef Id="cmp3D2A78302A6149F7464B0EDCD758BCCF" />
            <ComponentRef Id="cmp8C674FD6A69988A60A77A4CEE0F53781" />
            <ComponentRef Id="cmpDB4717CBBFD23A9652DB5B136ABB5D75" />
            <ComponentRef Id="cmpCF0F711637230B4D1AE41109C02C9142" />
            <ComponentRef Id="cmpF88B96E5973E0D28B511DC6371DB06E0" />
            <ComponentRef Id="cmpB139B49DF4DF8F44C525B449EA8187F7" />
            <ComponentRef Id="cmp5B65C45828B950384B8C5C76AB9F6EF0" />
            <ComponentRef Id="cmp5A9228A102598245A49CC73E4B42BFFD" />
            <ComponentRef Id="cmp0B11C97F8D96134C5A582DAA9D362721" />
            <ComponentRef Id="cmp22B9B089D6F03FEB02531ECB35C82F8E" />
            <ComponentRef Id="cmp958171B03EC06C56FB11A52D468E5F57" />
            <ComponentRef Id="cmpB322B77CE8D40EBAD199D45D0E4F25F0" />
            <ComponentRef Id="cmp920020A0D51F9A626EB2143066649049" />
            <ComponentRef Id="cmp6A573805E6F545A7F37C18527646950E" />
            <ComponentRef Id="cmp0D2F1CB83AD7A688791EFF1B2407B5F1" />
            <ComponentRef Id="cmp8D45D052C68877B0B807B3D45E104FF6" />
            <ComponentRef Id="cmpD91242D38C41E4403B7679B93F1EEBB4" />
            <ComponentRef Id="cmpCB80CFC92D7C1BB2787B948E67B42B03" />
            <ComponentRef Id="cmpBCCB7ADB11BD8E995C2D17B5FDFD7CA8" />
            <ComponentRef Id="cmp6300BF95DDDCF98EC047B2991C2BA653" />
            <ComponentRef Id="cmp087AEDA3ECF7BE8C1137AADA0E56E0A6" />
            <ComponentRef Id="cmpEBA035EA7685839B21FA1B833C2D781C" />
            <ComponentRef Id="cmp87BF3E7D495DC9B53F7ED2A371F1FE92" />
            <ComponentRef Id="cmp2220CCF66448F1A862D1353191CE69F5" />
            <ComponentRef Id="cmp791F5746D6F2AC68E2E8A50343B869F7" />
            <ComponentRef Id="cmp3DA139ADE5BC562B564DECE23AFFD8D0" />
            <ComponentRef Id="cmp3F52B8D89D587889C8A65D69E74B5F51" />
            <ComponentRef Id="cmp102AA2B65E2F7CFDBE0F937F8D225168" />
            <ComponentRef Id="cmp022B66C05DEF11B72F5542F7A563B670" />
            <ComponentRef Id="cmp0F72C70E7993CC0B3E9FF70ED40066D9" />
            <ComponentRef Id="cmpFA0036474721DE0D4163E05499F39951" />
            <ComponentRef Id="cmpB5AF9E63913432C07629EC20330320A3" />
            <ComponentRef Id="cmp9D66267AB1CAF7A98DFC42947DC635D4" />
            <ComponentRef Id="cmpCD4F94EB73F3962B42308170454B4366" />
            <ComponentRef Id="cmp6D7DA841FD268735AFB1026BA6AE24A3" />
            <ComponentRef Id="cmp08111D788677D8B8150650EE58FB5962" />
            <ComponentRef Id="cmp5A46DA40AED3B5E10AF9751BA0029C2C" />
            <ComponentRef Id="cmp6A6C2351815759B4DB8982A7741D0ABA" />
            <ComponentRef Id="cmp82623C6CA3D1FE2B38C69748720D46CB" />
            <ComponentRef Id="cmp2EAADFED8A771ED40D36F4261011FC42" />
            <ComponentRef Id="cmp0C35E5441CB1AEE868B0841FC2B3727D" />
            <ComponentRef Id="cmpF7B971FD5EDDB748109439252E62DBB2" />
            <ComponentRef Id="cmp1A38450971536177F12598D9DA69460B" />
            <ComponentRef Id="cmpB3C98B1AF19712A5A4C90299621D5AA3" />
            <ComponentRef Id="cmpB532E6FD17B9FD1DDEF930DAB1CDCC8C" />
            <ComponentRef Id="cmp930FCEACB08C3F828E26B2B4AAAD3B58" />
            <ComponentRef Id="cmp94D35364CD546AECFF1FD3E16E7705BC" />
            <ComponentRef Id="cmpEEB478F290FD8E012F256864DA59B87A" />
            <ComponentRef Id="cmpABBCFC94814B14153BE6A9A7989C2A0A" />
            <ComponentRef Id="cmpF242BF7465335E363684D1995205E1BD" />
            <ComponentRef Id="cmp02E6C2F0AD10D0478D86BE37452B0914" />
            <ComponentRef Id="cmp4A0D7430E5062327165BBC0627BB2583" />
            <ComponentRef Id="cmp39219EB53A18F9EF8C1D9E629B44B00E" />
            <ComponentRef Id="cmpA1E64C6DD02D1B8D3365CDF712DE7740" />
            <ComponentRef Id="cmp2F00835F6AB457CB0746B0CF23BBABC4" />
            <ComponentRef Id="cmp728A6879EC0D4538CF0D9A610CDB29AB" />
            <ComponentRef Id="cmpCF6F10CA4A3650B98898E76461DBDB47" />
            <ComponentRef Id="cmp512FC92BCC546D0A442E2A50E378BA60" />
            <ComponentRef Id="cmpA8FCAF75866687FC4A4693E426913FBA" />
            <ComponentRef Id="cmp747FF5C347AA12FFF91DF70F289BC1F7" />
            <ComponentRef Id="cmpDEF19AE67395660D7A04537C771DEAEA" />
            <ComponentRef Id="cmp286486FA354377E5944B31BCB5E1BD86" />
            <ComponentRef Id="cmpDA5F2E45468ACB6957DF118202F57CBA" />
            <ComponentRef Id="cmp329238427D6DFA82B9DE0EC84FAA175F" />
            <ComponentRef Id="cmp006F8D28BA0AFE320C8E136D5C68A581" />
            <ComponentRef Id="cmp538D88FA41B7B0483DDF492891D5D684" />
            <ComponentRef Id="cmpF9E68B4BB97E17771AA221E83025CF38" />
            <ComponentRef Id="cmpA38DF32DEFA15EAB22A6AF80CC0DBA93" />
            <ComponentRef Id="cmp7A14C98BD98024E214134EE58D8A2A0D" />
            <ComponentRef Id="cmpFB1DAD1066930B4BCF63BD47478DA044" />
            <ComponentRef Id="cmpD5C2C4A360A21B8188754FC87E3531E0" />
            <ComponentRef Id="cmp971F14265094A43D81FE6F2B7D1AF6B7" />
            <ComponentRef Id="cmp0326270DDC7B6B2E7294E885AF295E3A" />
            <ComponentRef Id="cmp514A78E3D9A3A1B0381C2609914F3FCD" />
            <ComponentRef Id="cmp3B994E9EC7D69DA30E3341DDCA1C2E35" />
            <ComponentRef Id="cmp8648F3FB6E0C32E344C77586438BA083" />
            <ComponentRef Id="cmpA160DA65B8DFE4CF4F6754B9B315896E" />
            <ComponentRef Id="cmp4242E026351F6B91ED373820F5BA7E70" />
            <ComponentRef Id="cmp42CC4971550CD97B0B702F1471CB4C72" />
            <ComponentRef Id="cmpF91962248A2205ABCF3B6BD33C74BAF4" />
            <ComponentRef Id="cmp5DEDEDAD272B08B21352520216DB4781" />
            <ComponentRef Id="cmp9173B268855879B81EDE2F0FD17367A7" />
            <ComponentRef Id="cmp5F4A3E3B2CBE10DA3D1BE6856D377E48" />
            <ComponentRef Id="cmpAEAABAB05E5E18C6E5D596B5134B11AA" />
            <ComponentRef Id="cmpB7F61D4C72FC6E25B4BD2D7C406028AF" />
            <ComponentRef Id="cmpF7B0EE03C7D98B064308BA96508AE479" />
            <ComponentRef Id="cmp86A1AADE6BF473BDAE88C6F24BCCA966" />
            <ComponentRef Id="cmp975438FFB4C20A8535CA709CDD345C48" />
            <ComponentRef Id="cmpAE73F552B8F7B3A26A0C4D716BDDB8B8" />
            <ComponentRef Id="cmp7858B731FC612FE7E07A6122BFDBA4D8" />
            <ComponentRef Id="cmp3CD942B25C15D4F3B3B8BA16662EFCEC" />
            <ComponentRef Id="cmp7BC7B696CC9C4EC000AAB5D52588B1BC" />
            <ComponentRef Id="cmp707551BC0DBA68C6D49E4ED09CC3FE90" />
            <ComponentRef Id="cmp515E95EEE930BE8B288A5B6D95C4F6B6" />
            <ComponentRef Id="cmpE060C6A31FDC9AA148DBE1CD795BDD87" />
            <ComponentRef Id="cmp51F55DD4FA3ECC6EC277B603BAE77E4B" />
            <ComponentRef Id="cmp09275652FE8A5CC3B05F9F04F4ACDAB8" />
            <ComponentRef Id="cmp4C12430D81FCE43486C72C98ACA22DE4" />
            <ComponentRef Id="cmpAF9DE5022005A570309CDC608D8817FE" />
            <ComponentRef Id="cmp864779AFDF069BB096C3D55EB7E67D17" />
            <ComponentRef Id="cmpBDCF4227A3F14BFD217701F4E1AEF581" />
            <ComponentRef Id="cmp8C2B056893FC9B4F917F1D60A86CAF46" />
            <ComponentRef Id="cmp5205763847DAE3B1F0E9A557ECEA0294" />
            <ComponentRef Id="cmpE22F274295C3DEF43785B45EC2A93623" />
            <ComponentRef Id="cmpB8A2E71C8CF36DE8D8F53A1D8C90371C" />
            <ComponentRef Id="cmp73A0603CACC8FD37AE5400E72FB390B4" />
            <ComponentRef Id="cmp2F2ED6725809828FFA8AF2B1F4793156" />
            <ComponentRef Id="cmpDA5844562D73C6F04F932F5314A77A39" />
            <ComponentRef Id="cmp7C9F2443CAE1F55295CD79951408C721" />
            <ComponentRef Id="cmpA65D953E5A54247042B256470D47D4AB" />
            <ComponentRef Id="cmp51F02589BA588D783C3C603656194CC7" />
            <ComponentRef Id="cmp5937FF9962810B779AC2D3AB0E1FFA31" />
            <ComponentRef Id="cmpB4F75E93D852D00850CC0545706516AC" />
            <ComponentRef Id="cmpC482BD0E23AD6B0866F0EC3B3EE21912" />
            <ComponentRef Id="cmp20D34FC7203469574D5B870FBFDB6F7F" />
            <ComponentRef Id="cmpA826E1BF780AE0933557676389100061" />
            <ComponentRef Id="cmp2A2D126124E8909219DB6B0BD3DB7281" />
            <ComponentRef Id="cmp48F0DEF6E07C958C489DB5F099A47D02" />
            <ComponentRef Id="cmpE51D0DCA6EE2771B65D0DB930DA0F422" />
            <ComponentRef Id="cmp16DCE2C779691329ACBD41A17893807C" />
            <ComponentRef Id="cmp607A37F44559C1B9663107B3C5780416" />
            <ComponentRef Id="cmp3750CA84737F30C6A133B736D82311DC" />
            <ComponentRef Id="cmp5F48A2E610A688238A2DF46678BFC4DA" />
            <ComponentRef Id="cmp333F8CFB28D84B1BFBCFD0207AB4C8DC" />
            <ComponentRef Id="cmpED48E5DDB3EBB7C71EDACF54D349688E" />
            <ComponentRef Id="cmpFA624270AF509809FE8CD8C49FA60779" />
            <ComponentRef Id="cmp50C00207A15C4550FE7A85241C74BBE8" />
            <ComponentRef Id="cmp56887909ACB3B8F6402B40E26751C3B3" />
            <ComponentRef Id="cmp0976629DB2D3387B7524A1EA5BB9828A" />
            <ComponentRef Id="cmp9BEE2BBA2E625E10ACE5D38F9CE29E25" />
            <ComponentRef Id="cmp1740817C651EE407F3A14689504EEF0B" />
            <ComponentRef Id="cmpB1F2210BCA59E771BFE567C4B70223E3" />
            <ComponentRef Id="cmpA098BA5EC2A20A12327DB7E9D1560C36" />
            <ComponentRef Id="cmp4DBC5ACFDAEC1C4E3CD7EF1AC171CDD4" />
            <ComponentRef Id="cmp1173314C87D3A1C6669E796D63BA0B5D" />
            <ComponentRef Id="cmp0A248A654EDFBDA44693AADCAC9DD461" />
            <ComponentRef Id="cmp9DB136D1B06E1CFF3226F8FF247FA400" />
            <ComponentRef Id="cmpDCFCF9BD3503D6340AA0A2B21FE7FBCC" />
            <ComponentRef Id="cmpD1D9EEDAFC075B3BC32EE7298288086F" />
            <ComponentRef Id="cmp740321EAD6FA852678D49E02C9131145" />
            <ComponentRef Id="cmp743C84704C46065CC2390782C88647FE" />
            <ComponentRef Id="cmpC370C60937565F7FB65302F95A8C1FF0" />
            <ComponentRef Id="cmpE9537DAAFB13ACF42382B5F39E041AAE" />
            <ComponentRef Id="cmp3AE669088A014BAB8C199390E02DB7E7" />
            <ComponentRef Id="cmpAB7158EA13F736C1E0451D0807BE4947" />
            <ComponentRef Id="cmpBE312FE3FB6A6BDDAB0FE75F1EC0F480" />
            <ComponentRef Id="cmp9D0A4D86ADBE049A6CD726A4C5FD96EE" />
            <ComponentRef Id="cmp6C9D44905338F4A80BCF436FADD3333E" />
            <ComponentRef Id="cmpED3B8CFD2C58E76550E55BB568433B01" />
            <ComponentRef Id="cmpBA0FF53077EEA56D55F8AB637925580B" />
            <ComponentRef Id="cmp63CB25923717C691B1A5EA40B6C111F0" />
        </ComponentGroup>
    </Fragment>
</Wix>

 Добавьте этот новый файл в проект инсталлятора (Solution Explorer -> Add -> Existing Item).

Product.wxs

Теперь, перейдем в файл Product.wxs. Если кратко, то это основной файл, в котором описывается вся логика создания инсталлятора, его конфигурация и метаданные. Для небольших решений проект wix может в полне себе состоять только из этого файла.

Давайте добавим компоненты в сам инсталлятор. Для этого нам необходимо перед закрывающимся тегом </Wix> удалить узел <Fragment> (он генерится Wix по-умолчанию при создании проекта) на следующую секцию:

<Fragment>
	<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
      		<ComponentGroupRef Id="PublishedComponents"/>
	</ComponentGroup>
</Fragment>

Таким образом, мы создали группу компонентов ProductComponents, которые будут развернуты по пути соответствующему свойству INSTALLFOLDER (она же виртуальная директория), при этом сами компоненты мы передали по ссылке из группы PublishedComponents, сгенерированной c помощью Heat.exe.

Удалите тег <MediaTemplate/> (ищите внутри тега Product) — он используется в качестве заглушки и, если его не удалить, то вы обнаружите, что вместе с .msi-файлом генерится .cab-файл. Нам же необходимо поместить его внутрь файла .msi. Для этого перед закрывающимся тегом <Product> необходимо добавить тег <Media>:

<Media Id="1"
           Cabinet="media.cab"
           EmbedCab="yes"
           DiskPrompt="CD-ROM #1" />
<Property Id="DiskPrompt"
           Value="$(var.ProductName) CD-ROM #1" />

Тем самым мы описываем компонент media.cab – архив с файлами для установки. EmbedCab=”yes” – указывает на то, что архив будет встроен в .msi-файл, а свойство DiskPrompt="CD-ROM #1" – является легаси-наследием со времен, когда программные продукты распространялись на материальных носителях и разработчикам инсталляционных пакетов приходилось решать проблему поставки продукта на нескольких дисках из-за нехватки дискового пространства на носителях. Также не забываем добавить Property со ссылкой на DiskPromt, чтобы Windows Installer мог создать сообщение пользователю о необходимости вставить определенный диск. Обращаю внимание, что DiskPrompt является необязательным, и, если вы не планируете поставлять ваш продукт на физическом носителе, то и проставлять его ненужно (то же самое касается и Property Id=»DiskPromt»).

Теперь нам необходимо добавить интерфейс для взаимодействия с пользователем: сделать это можно двумя путями. Или самостоятельно описывать интерфейс, или воспользоваться готовыми шаблонами, которые поставляются вместе с wix. Так как разработка интерфейса – это очень объемная тема, мы воспользуемся готовым решением.

Щелкаем правой клавишей по названию проекта в Solution Explorer -> Add Reference — открываем папку, в которую был установлен WiX, подкаталог bin, файл WixUIExtension.dll.

Снова перед закрывающимся тегом <Product> добавляем следующий код:

    <Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" ></Property>
    <UIRef Id="WixUI_InstallDir"/>

Wix предлагает пользователю несколько сценариев пользовательского интерфейса один из которых называется WixUI_InstallDir и, как можно догадаться из названия, позволяет пользователю выбирать в какую директорию будет произведена установка продукта. Путь до выбранной директории передается через свойство INSTALLFOLDER, которое используется в шаблоне WixUI_InstallDir на что и указывается Id="WIXUI_INSTALLDIR".

Работа с IIS

Для установки проекта, в нашем случае, описанных шагов недостаточно – не случайно же был выбран web-проект: теперь его нужно затащить на IIS. Разработчики Wix позаботились о нас и добавили в пакет поставки WixIISExtention – расширение, позволяющее развернуть приложение на web-сервере.

Подключаем расширение WixIISExtention: правая кнопка маши по проекту -> Add Reference — директория в которую установлен WiX, подкаталог bin, файл WixIISExtension.dll. У меня здесь C:\Program Files (x86)\WiX Toolset v3.11\bin\WixIISExtension.dll

Снова правая кнопка мыши по проекту инсталлятора -> New item… -> Wix/v3 и выбираем Installer File (.wxs). Назовем его IISConfiguration.wxs. Стираем все, что находится внутри файла и заменяем на следующее содержание:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:iis="http://schemas.microsoft.com/wix/IIsExtension">
    <Fragment>
    <DirectoryRef Id="TARGETDIR">
      <!--Creating an application pool-->
      <Component Id="BlazorAppPool"
                 Guid="{5766F29A-7FD5-4359-BD6C-5E5C543FEFFD}"
                 KeyPath="yes"
                 Win64="yes">
        <iis:WebAppPool Id="BlazorAppPool"
                        Name="BlazorAppWebSite"
                        Identity="localSystem"
                        ManagedPipelineMode="Integrated"
                        ManagedRuntimeVersion="v4.0"/>
      </Component>
      <!--Setup IIS for Blazor App-->
      <Component Id="InstallWebsite"
                 Guid="{4AB0376B-F778-4D0F-8CA6-2F308AB7B077}"
                 KeyPath="yes">
        <iis:WebSite Id="BlazorApp"
                     Description='BlazorAppWasm'
                     Directory='INSTALLFOLDER'
                     AutoStart='yes'
                     StartOnInstall='yes'>
          <iis:WebAddress Id="localhost_BlazorApp"
                          Port="8085" IP="127.0.0.1"/>
          <iis:WebApplication Id="BlazorWasmApplication"
                              Name="Blazor Web Application"
                              WebAppPool="BlazorAppPool"/>
        </iis:WebSite>
      </Component>

    </DirectoryRef>

    <ComponentGroup Id="BlazorAppIisConfiguration">
      <ComponentRef Id="InstallWebsite"/>
      <ComponentRef Id="BlazorAppPool"/>
    </ComponentGroup>
    </Fragment>
</Wix>

Давайте разберем по тегам содержимое файла:

  • внутри тега Wix добавляем ссылку на IISExtention c помощью вот этого атрибута xmlns:iis="http://schemas.microsoft.com/wix/IIsExtension". Не забываем это делать, иначе проект не заведется.

  • внутри тега Fragment начинаем описывать настройку IIS. Так как все компоненты должны получить путь установки обязательно упаковываем их в тег Directory или DirectoryRef, если директория уже объявлена. В нашем случае это TARGETDIR – корень виртуального каталога, объявленный на стадии создании проекта Wix

  • объявляем компонент с помощью тега Component, присваиваем ему ID – не забывайте, что Id должен быть уникальным для каждого компонента (помним, что для базы данных Windows Installer он выполняет роль первичного ключа). Генерим GUID любым удобным для вас способом. Я предпочитаю использовать средства Visual Studio (Tools -> Create GUID и выбрать Registry Format). Указываем компоненту свойство keypath=”yes” – это необходимо, чтобы установщик удостоверился, что данный компонент не был ранее установлен чтобы избежать перетирания существующих версий компонента (будет заменен только в том случае, если будет предложена более новая версия компонента), а также для осуществления восстановления.

  • Внутри компонента описываем настройки AppPool для IIS: прописываем уникальный Id, имя пула, указываем тип учетной записи – в нашем случае это LocalSystem (желающие получить дополнительную информацию о них могу перейти по ссылке https://windowsnotes.ru/iis/application-pool-identities-v-iis/). Указываем режим конвейера Integrated и последнюю доступную версию .net clr.

После того, как нами были описаны настройки WebPool’а мы должны сконфигурировать сайт, для чего снова создается новый компонент. Назовем его «InstallWebsite»:

  • Конфигурация сайта производится с использованием свойств тега <iis:WebSite>. Через свойства тега передаем его Id (помним, что он должен быть уникальным), описание и  виртуальную директорию. Чтобы после установки получить сразу работающий проект, не требующий от пользователя дополнительных телодвижений добавим свойствам AutoStart и StartOnInstall значение yes.

  • С помощью свойств тега iis:WebAddress передадим адрес сайта: в нашем случае он запустится локально на порту 8085 (можете выбрать любой доступный порт)

  • В теге iis:WebApplication мы указали связь сайта с WebPool’ом

На этом IIS можно считать сконфигурированным. Теперь создаем группу компонентов с названием BlazorAppIisConfiguration (см. 35-ю строчку) и закидываем в нее два наших созданных выше компонента (с описанием конфигурации AppPool’а и сайта).

И снова Product.wxs

Снова открываем файл Product.wxs. Добавляем перед закрывающимся тегом </Product> тег <Feature> со следующим содержимым:

<Feature Id="BlazorAppFeature"
             Title="BlazorWasmApplication"
             Level="1"
             ConfigurableDirectory="INSTALLFOLDER"
             AllowAdvertise="no"
             Absent='disallow'>
      <ComponentGroupRef Id="BlazorAppIisConfiguration" />
      <ComponentGroupRef Id="PublishedComponents" />
</Feature>

Первые два свойства традиционно Id и Название. Что касается свойства Level – оно служит для включения (при значении «1») или исключения (при значении «0») фичи из процесса установки. Делается это, как правило, путем добавления публичного свойства (тег Property), которое может принимать значение через аргументы командной строки или иными способами и последующим использованием через тег Condition, который должен располагаться внутри тега <Feature>. Обязательно разберем работу с условиями, но не в этой статье.

Свойство ConfigurableDirectory указывает на название виртуальной директории в которой будет лежать наш программный продукт, нуждающийся в разворачивании на IIS. Свойства AllowAdvertise="no" и Absent='disallow‘ используем с указанными значениями, так как мы не планируем предоставлять пользователю возможность кастомизации процесса установки в части управления параметрами настройки IIS и записи файлов проекта.

Далее, внутрь указанного тега кладем ссылки на описанные ранее группы объектов (см. 7 и 8 строчки).

Теперь нам необходимо установить связь виртуальной директории, являющейся корневой для нашего проекта, с адресом в дисковом пространстве компьютера пользователя куда будет непосредственно установлен проект. Делается это следующим образом:

<Fragment>
		<Directory Id="TARGETDIR" Name="SourceDir">
			<Directory Id="ProgramFilesFolder">
				<Directory Id="INSTALLFOLDER" Name="InstallerForBlazorApp" />
			</Directory>
		</Directory>
</Fragment>

При создании проекта Wix внутри файла Product.wxs сразу после тега <Product> у вас уже будет шаблон, обозначенный тегами <Fragment>  — замените его на код указанный выше. По сути, несмотря на то, что теги являются вложенными и кажется, что при установке будет создана иерархическая структура, фактически все файлы будут установлены в папку, которая будет выбрана пользователем во время установки, т.к. property WIXUI_INSTALDIR (как было описано выше, с помощью этого свойства шаблону UI передается виртуальный путь) содержит ссылку на виртуальную директорию INSTALLFODER, которая является корнем для нашего проекта.

Что касается тега Fragment, то с помощью него достигается структурирование проекта. Раздел, помещенный внутрь тега Fragment, может быть перемещен в отдельный файл или расположен практически в любом месте файла. Иначе, пришлось бы все инструкции для создания инсталлятора помещать внутрь тега Product.

Конечный вариант файла Product.wxs

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
	<Product Id="*" Name="InstallerForBlazorApp" Language="1033" Version="1.0.0.0" Manufacturer="Developer" UpgradeCode="543f9f1d-2c37-403d-930c-f0eb8bf401ec">
		<Package InstallerVersion="500" Compressed="yes" InstallScope="perMachine" Platform="x64"/>

		<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />

    <Media Id="1"
           Cabinet="media.cab"
           EmbedCab="yes"
           DiskPrompt="CD-ROM #1" />
    <Property Id="DiskPrompt"
              Value="InstallerForBlazorApp CD-ROM #1" />


    <Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" ></Property>
    <UIRef Id="WixUI_InstallDir"/>

    <Feature Id="BlazorAppFeature"
             Title="BlazorWasmApplication"
             Level="1"
             ConfigurableDirectory="INSTALLFOLDER"
             AllowAdvertise="no"
             Absent='disallow'>
      <ComponentGroupRef Id="BlazorAppIisConfiguration" />
      <ComponentGroupRef Id="PublishedComponents" />
    </Feature>
	</Product>

	<Fragment>
		<Directory Id="TARGETDIR" Name="SourceDir">
			<Directory Id="ProgramFilesFolder">
				<Directory Id="INSTALLFOLDER" Name="InstallerForBlazorApp" />
			</Directory>
		</Directory>
	</Fragment>

</Wix>

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

<Fragment>
	<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
      		<ComponentGroupRef Id="PublishedComponents"/>
	</ComponentGroup>
</Fragment>

Для лаконичности .xml-описания в нашем случае можно отказаться от создания еще одной группы компонентов внутри файла Product.wxs и добавить ссылку на существующую группу в Feature— см. 26 строку файла Product.wxs.

После того, как все необходимые .xml документы будут созданы, давайте соберем проект: правая кнопка мыши по проекту wix -> build. После сборки из папки проекта перейдем по следующему пути: ~\InstallerForBlazorApp\bin\Release (или Debug — в зависимости от выбранной вами конфигурации сборки проекта в Visual Studio) – в нем лежит собранный инсталлятор InstallerForBlazorApp.msi. Запускаем его:

Принимаем лицензию (так как мы не передавали файл лицензии, то имеем Lorem impsum…)

Далее мы имеем возможность выбрать директорию, в которую будет произведена установка продукта (по умолчанию, Program Files (x86))

Next, next, install.

После положительного ответа на запрос разрешения на установку, продукт будет развернут в указанной директории.

Убедиться в этом вы можете сами, перейдя в директорию установки. Однако, это еще не говорит о том, что все прошло по плану. Откройте IIS -> Application Pool. Там должен появится созданный нами новый пул приложений

А в папке сайтов появится новый BlazorAppWasm

Нажимаем на Browse: http://127.0.0.1:8085/ и в браузере открывается страница установленного проекта, после чего установку можно считать успешной.

Удалить приложение вы можете или через установку и удаление программ, или непосредственно через инсталлятор путем его повторного запуска. При этом, будет произведено не только удаление файлов, но и пула с сайтом из IIS.

Таким образом, можно резюмировать, что технология Wix позволяет относительно быстро описать и собрать инсталлятор (который позволяет произвести выбор директории установки) для достаточно большого проекта – главное знать какие теги и в каком порядке использовать.

При наличии у хабрчан интереса к данной теме, я планирую подробно рассказать про работу с реестрами, создание пользовательских действий, разработку интерфейса, внедрение скриптов в процесс установки, написание бутстрапера, а также использование расширений и инструментов, поставляемых вместе с Wix.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Продолжать писать про Wix toolset?

25.58% Я томат — любому варианту рад11

Проголосовали 43 пользователя. Воздержался 1 пользователь.

Часть 1

Знакомство пользователя с программой чаще всего начинается с запуска инсталлятора. Внешний вид («упаковка») и функциональность продукта определяется разработчиком. Пользователю нужно иметь возможность проконтролировать процесс, выставив нужные параметры установки. Для разработчика же важно, чтобы, как минимум, его программа была установлена корректно, а инсталлятор был совместим с необходимыми платформами.

Решений для создания инсталляторов достаточно много. Чаще всего используется подсистема Windows Installer, которая уже входит в инструментарий операционной системы. Но существуют и альтернативные решения — как платные, так и бесплатные, различной функциональности. Зачастую с их помощью можно создавать пакеты с инсталлятором, не зависящим от Windows Installer.

Путеводитель включает в себя всевозможные системы для создания инсталляторов, основные аспекты их обзора следующие:

  • Среда разработки, интерфейс, поддержка сценариев
  • Работа с проектом, типы создаваемых пакетов, возможности импорта проектов из других сред разработки
  • Пользовательские опции инсталлятора: поддержка языков, профилей и другие опции
  • Поддержка расширений

NSIS (Nullsoft Scriptable Install System)

Домашняя страница: http://nsis.sourceforge.net/

Меню NSIS

NSIS — бесплатный и широко известный инструментарий для создания инсталляционных пакетов в среде Windows. Отличительные особенности — компактность, масштабируемость, поддержка плагинов и локализаций. Из других возможностей NSIS: поддержка сценариев, различных вариантов установки (включая несколько проектов внутри одного инсталлятора), создание веб-инсталляторов.

Дистрибутивы NSIS создаются на основе сценариев. Переменные, функции полностью контролируют как инсталляцию, так и деинсталляцию продукта. С помощью скриптов можно добавлять файлы и директории, вносить изменения в реестр, редактировать текстовые и двоичные файлы, создавать патчи, управлять переменными среды и даже обращаться к Windows API (посредством расширений).

Синтаксис языка NSIS достаточно прост и удобен для чтения, основная документация к нему доступна здесь. Более того, в комплекте с программой содержится большое количество примеров (файлы формата nsi доступны в папке Examples). Для редактирования nsi-сценариев пригоден любой редактор кода, где без особых усилий можно включить подсветку синтаксиса. Множество задач сразу унифицируется, если использовать специальный плагин для IDE Eclipse, EclipseNSIS, либо Venis. Venis представляет собой интуитивную визуальную среду для создания сценариев.

Мастер настройки инсталлятора Venis

Удобно работать с NSIS в связке и с другими программами, например, Excelsior Installer (см. ниже).

Если возникает необходимость расширить возможности инсталлятора, можно добавить определенные функции. Плагины пишутся на C, C++, Delphi или других языках. Готовые примеры расширений доступны здесь. Функции разнообразны: от визуальных эффектов инсталлятора до создания патчей и обращения к Windows API.

Скомпилировать инсталлятор можно с помощью инструмента makensis, предварительно выбрав тип компрессии — ZLib, BZip2 или LZMA. Кроме того, сам по себе инсталлятор занимает немного места — всего 34 КБ.

Графический интерфейс инсталлятора доступен в одном из двух вариантах исполнения — Classic или Modern. Более функциональный Modern (на данный момент используется его версия 2.0) позволяет создавать страницы мастера установки с использованием текста, шрифтов, изображений, диалогами, опциями и др. На данном этапе помощь окажет программа NSIS Dialog Designer. Она позволяет быстро конструировать интерфейс, а полученный результат сохранять в формат nsdinc, который затем несложно интегрировать в .nsi-скрипт.

Резюме. Среда NSIS уже давно зарекомендовала себя, и в доказательство — список разработчиков, которые используют ее возможности. Несложный язык сценариев, наличие всех необходимых функций, возможность расширения, доступность основных и дополнительных инструментов — за счет всего этого NSIS составляет сильную конкуренцию программам в данной категории.

Inno Setup

Домашняя страница: http://www.jrsoftware.org/

Inno Setup — бесплатный инструментарий для создания инсталляторов на базе сценариев. Среди главных особенностей продукта — работа со всеми версиями ОС Windows (Windows 2000 и выше), расширенная поддержка 64-битных приложений, настраиваемые типы установки, встроенный препроцессор и мощный язык сценариев на основе Pascal.

Сценарии имеют структуру, характерную конфигурационным файлам ini-формата, поэтому код вполне хорошо читаем и удобен в редактировании. Документ разделен на секции, и каждая из них отвечает за определенную задачу инсталлятора соответственно. Всего имеется два типа секций — с параметрами и «директива—значение».

Разработчикам, знакомым с Pascal, будет на руку тот факт, что Inno использует «родственный» язык — RemObjects Pascal Script. Сценарии отвечают за добавление новых опции, создание интерфейса, вызов файлов или библиотек, настраиваемые действия (custom actions) и т. д. В рабочей папке Inno Setup находятся примеры скриптов (также доступны в меню компилятора). По умолчанию в Inno Setup входит компилятор сценариев Compiler IDE. Для быстрого старта рекомендуется также установить Inno Script Studio. Этот редактор проектов входит в редакцию QuickStart Pack, скачать ее можно здесь. Для упрощения задач может быть полезен визуальный редактор сценариев — IsTool.

Создание сценария Inno Setup в ISTool

Самый простой вариант создания инсталлятора — обратиться к пошаговому мастеру настройки Inno Script Studio. Здесь указывается информация о продукте, координаты программы, файл лицензии и другие данные, языки локализации, опции компилятора. Впоследствии проект доступен для компиляции, отладки либо модификации полученного сценария в окне редактора.

Редактор Inno Script Studio

Редактор Inno Script Studio доступен на русском языке. Значительно проще настраивать проект последовательно, переходя по секциям, а не создавая сценарий с нуля. При добавлении нового элемента изменения вносятся в код сценария, синтаксис подсвечивается, код соответствующим образом разбит на секции ([Setup], [Types], [Components]…).

Разделы редактора не сгруппированы, но структура вполне узнаваема. Логически их можно разделить следующим образом:

  • Содержимое дистрибутива: Файлы, Каталоги, Иконки, Файлы INI, Реестр
  • Сообщения и пользовательские сообщения,
  • Пользовательские опции: Типы, Компоненты, Задачи, Языки
  • Действия: Выполнить, Удалить перед установкой, Выполнить перед деинсталляцией, Удалить после деинсталляции
  • Код сценария: Код Паскаля, Этапы предкомпиляции, Этапы посткомпиляции

Русская локализация иногда вводит в заблуждение, как всегда и обстоит с не очень качественным переводом.

Из других особенностей Inno Setup — тихая инсталляция и деинсталляция. Пользователю доступны различные типы установки и локализации на выбор. Установщик может быть зашифрован, содержать цифровую подпись либо защищен паролем. К дистрибутиву может применяться bzip2- или LZMA/LZMA2-компрессия. Интерфейс — в стиле 2000/XP, иных вариантов не предусмотрено.

Резюме. Inno Setup — ближайшая альтернатива NSIS. Позволяет задействовать как мощный язык сценариев, так и удобный и гибко настраиваемый редактор Inno Script Studio, доступный практически «из коробки».

IzPack

Домашняя страница: http://izpack.org/

Чаще всего, среда разработки инсталлятора закреплена за определенной платформой, и разработчик вынужден использовать различный инструментарий для каждой из них. IzPack решает вопрос кроссплатформенности, используя для своих нужд универсальную среду разработки Java.

Главные особенности IzPack: XML-синтаксис, интеграция с различными инструментами компиляции, простой и гибкий API-интерфейс, возможность локализации.

Принцип создания инсталлятора в IzPack

источник

Среди особенностей инсталляторов, созданных средствами IzPack, — небольшой размер и модульность. В основе дистрибутива лежит XML-документ, где указываются все необходимые спецификации, определяется функциональность продукта. Впоследствии конфигурационный файл обрабатывается любым удобным способом, для этого используется командная строка или Apache Ant. Для наращивания функциональности инсталлятора могут быть задействованы IDE среды, такие как Eclipse, IntelliJ IDEA или Netbeans. Для составления конфигурационного файла подойдет любой редактор кода.

В XML-документе указывается информация о проекте (), интерфейс (), локализации (), файлы (), ресурсы (), панели (), содержимое ( — может быть упаковано в raw, gzip, bzip2) и др. Что касается java, в IzPack есть возможность применения действий (custom acrions) и переменных — встроенных, пользовательских и переменных среды (см. документацию и неофициальное руководство).

Для создания графического интерфейса инсталлятора предназначены панели. С их помощью определяется внешний вид, экрана приветствия, содержимое, текстовая информация (readme, лицензии), изображения. Поддерживаются различные типы интерактивных элементов (поля, переключатели и т. д.), локализация, включая русскую. Переводу поддается как интерфейс, так и содержание.

PackJacket, GUI-надстройка для IzPack

Для создания самораспаковывающихся модулей применяется метод 7-Zip SFX, использующий возможности известного архиватора. Для Mac OS также доступна оболочка под названием izpack2app.Кроме того, есть возможность создания веб-инсталлятора, для этих целей присутствует оболочка izpack2jnlp, использующая возможности Java Web Start. IzPack поддерживает опцию тихой установки.

Оболочка UPX для создания самораспаковывающихся инсталляторов

Резюме. IzPack — одна из немногих кроссплатформенных систем для создания инсталляторов. Процесс написания конфигурации, компиляции и отладки удобен за счет интеграции со средами разработки, несложен в освоении. Из недостатков следует отметить значительно устаревший (и не оригинальный — native) вид получаемого инсталлятора.

Excelsior Installer

Домашняя страница: http://installer.excelsior-usa.com/ru/

Работа с проектом в Excelsior Installer

Excelsior Installer — бесплатная программа, предназначенная для создания инсталляторов и обновлений. Основные особенности — простая интуитивная графическая оболочка, возможность интеграции с Проводником и NSIS.

Создание дистрибутива или обновления производится с помощью упаковщика (Packager). Он содержит пошаговый мастер, содержащий настройки проекта. На основе проекта очень просто скомпилировать восьмишаговый инсталлятор. Согласно описанию, это делается и вовсе двумя кликами мыши, но в обязательном порядке в упаковщике необходимо определить следующие параметры:

  • Файлы и папки приложения, ярлыки
  • Описание: имя компании, название продукта, версия продукта

Упаковщик состоит из разделов Files (Файлы), Settings (Настройки) и Appearance (Внешний вид). В целом, здесь содержится стандартный перечень опций, отвечающих за создание лицензионного соглашения, выбор инсталляционной директории, ярлыков, ключей реестра и другие параметры. Если изучить таблицу сравнения продуктов, легко обнаружить следующий функциональный «пробел»: инсталлятор не поддерживает файловые ассоциации, DLL-расширения, элементы управления.

Что касается доступных опций инсталлятора — можно указать профиль установки, в зависимости от привилегий текущего пользователя. Инсталлятор поддерживает локализацию, причем русский язык доступен «из коробки», остальное скачивается отдельно. Возможна автоматическая — тихая — инсталляция без запроса данных у пользователя, после установки — проверка целостности пакета или другие настраиваемые действия.

Как уже было упомянуто, возможна интеграция Excelsior с NSIS. Excelsior Installer, по сути, выступает полноценным GUI для NSIS, настройки проекта экспортируются без проблем.

В ряду с этим участником обзора, стоит выделить еще один родственный продукт — Excelsior Delivery. По большей части функции Excelsior Installer дублируются. Но есть также и несколько дополнительных функций: добавление в систему OLE- и ActiveX-элементов, файловых ассоциаций, библиотек, создание опросов пользователей. Лицензионная версия Excelsior Delivery (стоимостью $99) позволяет также применить к установщику фирменное оформление (branding). Если эта опция неважна, можно скачать некоммерческую версию программы.

Резюме. Excelsior Installer — простая и очень понятная система для создания дистрибутивов, может использоваться как надстройка к NSIS. Обратная сторона медали — усредненная функциональность как Excelsior Installer, так и Delivery.

WiX Toolset

Домашняя страница: http://wixtoolset.org/

WiX (Windows Installer XML) — бесплатный набор инструментов для создания инсталляторов (Windows Installer) с использованием спецификации XML. Из особенностей: интерфейс командной строки, интеграция с IDE, автоматизация процессов, поддержка базовых и расширенная поддержка Windows Installer.

Ядро WiX составляют компилятор (candle), компоновщик (light), библиотекарь (lit), декомпилятор (dark), бутстраппер инсталляции (burn) и другие утилиты. С их помощью можно создавать пакеты инсталляции .msi, модули слияния .msm, патчей .msp.

Создание инсталлятора состоит из нескольких основных этапов: разработка сценария, его проверка, обработка препроцессором, компиляция и компоновка. Для сборки инсталлятора и автоматизации в целом используется платформа MSBuild. Автоматизация — одно из главных преимуществ WiX при работе с достаточно ресурсоемкими проектами.

Исходный код имеет формат XML (расширение файла wxs). Сценарий описывает все этапы установки, начиная с описания проекта заканчивая действиями после установки. Редактировать его можно в любом редакторе с поддержкой данного формата.

WiX радует своими интеграционными возможностями: WiX Toolset предоставляет интерфейс командной строки. Для работы с проектом в Visual Studio (модуль IntelliSense) потребуется расширение Votive.

В затруднительных ситуациях или при отсутствии времени на изучение сценариев, хорошую службу окажет графическая оболочка WiXEdit. Ее основные преимущества — импорт существующих wxs-проектов, структурирование xml-данных с удобным чтением и навигацией. С помощью мастера также несложно создать инсталляционный файл с нуля. Причем это далеко не единственный подобный инструмент (см. здесь).

Определение функциональности в WiX Edit

Резюме. В данном случае, многое решает спецификация XML. WiX дает возможность программистам оперировать исходными данными, не прибегая к графической оболочке. В состав WiX входят все необходимые инструменты, вдобавок к этому функциональность инсталлятора может быть улучшена за счет расширений.

Nullsoft Scriptable Install System is also known as NSIS open-source system to create Windows application installers. NSIS is a script-based system allowing you to create the logic behind your installer/setup file in a complex way to install tasks. NSIS offers plug-ins and other scripts, for example, to download/install 3rd-party files or communicate with Windows.

The tutorial application

This tutorial will guide you through installing and creating your first Windows installer with Nullsoft Scriptable Install System and how to compile your project. Captura Portable will be used as «our application» for the sake of this tutorial.

Installation

Head to NSIS official site and download the latest release and install it. Run NSIS and you will be welcomed with a menu like below, It’s always a good practice to read the Documentation before jumping in to it.

Structure

Structure is key, not only in code/scripting but also in everyday life. Structuring your files and folder is important for easy access, locate various files and versions.

Navigate to your Documents and create a new folder named NSIS and sub-folder after your project name, In our case Captura. Your path should look something like this

C:\Users\Bitxo\Documents\NSIS\Captura

Navigate in to your project directory «Captura» and create following files and folders.

Captura
 ├── app
 ├── assets
 ├── license.txt 
 ├── redist
 └── setup.nsi 
  • app directory is for your project, You can also pretend that it is «root» directory for your project.
  • assets: This directory is only for NSIS script.
  • license.txt: (Optional) Can be located in your app directory. Show license to end-user in the install application.
  • redist: this directory you can include DirectX or any other third-party software needed for your install application (Parent folder for each third-party software).

Your file/directory structure should look similar to the Captura example witch also covers third-party software in its tree.

Captura
 ├── app
 │   ├── captura-cli.exe 
 │   ├── captura-cli.exe.config
 │   ├── captura.exe 
 │   ├── captura.exe.config
 │   ├── keymaps 
 │   ├── languages 
 │   ├── lib
 │   ├── licenses
 ├── assets
 │   ├── head.bmp 
 │   └── welcome.bmp
 ├── license.txt
 ├── redist
 │   └── directx
 │       └── dxwebsetup.exe
 │
 └── setup.nsi 

BITMAP (Optional)

NSIS offers header and welcome image in bmp format. Great opportunity to promote your company or maybe another project you may have.

MUI_HEADERIMAGE_BITMAP MUI_WELCOMEFINISHPAGE_BITMAP
head.bmp welcome.bmp
150×57 pixels 164×314 pixels

The beginning of scripting

NSIS language for scripting is something between PHP and assembly, slightly more to assembly.

Lines starting with ; are comments, You may also comment out lines of code but comments placed before code will be ignored.

Edit setup.nsi in your project directory with your favorite text editor. At the start of the document we need to including a few things.

  • MUI2.nsh also know as Modern User Interface 2 provides a user interface (UI).

  • logiclib.nsh provides familiar logic and easier flow with things like if, else, while loops etc.

;--------------------------------
; Includes

  !include "MUI2.nsh"
  !include "logiclib.nsh"

About !define

The !define commands will add gflag to the global define list, in other words when you declare !define it will be global and accessed all over the script and even inside another !defines.

Create global define with !define

Retrieve data from hello

Remove item from the global define list with undef

Add defines

The purpose with this define list is to avoid entering same content multiple times, In the next step this will make sense.

;--------------------------------
; Custom defines
  !define NAME "Captura"
  !define APPFILE "captura.exe"
  !define VERSION "7.0.0"
  !define SLUG "${NAME} v${VERSION}"

General

At first glance you noticed repeated calls to custom defines in the previous step and other arguments.

  • Name: Set name of the installer window.
  • OutFile: Set name of compiled installer by MakeNSISW.
  • InstallDir: Specify the default installation directory manualy or with constants.
  • InstallDirRegKey: Tells the installer to check a string in the registry and use it as the install dir if valid.
  • RequestExecutionLevel: Specifies request by user level.
;--------------------------------
; General

  Name "${NAME}"
  OutFile "${NAME} Setup.exe"
  InstallDir "$PROGRAMFILES\${NAME}"
  InstallDirRegKey HKCU "Software\${NAME}" ""
  RequestExecutionLevel admin

Icon & Banners

Set Icon, Banners and Welcome title message.

;--------------------------------
; UI
  
  !define MUI_ICON "assets\captura.ico"
  !define MUI_HEADERIMAGE
  !define MUI_WELCOMEFINISHPAGE_BITMAP "assets\welcome.bmp"
  !define MUI_HEADERIMAGE_BITMAP "assets\head.bmp"
  !define MUI_ABORTWARNING
  !define MUI_WELCOMEPAGE_TITLE "${SLUG} Setup"

Pages

Define pages to use with !insertmacro witch inserts content from a macro created with !macro. Pages will appear in the order you set.

;--------------------------------
; Pages
  
  ; Installer pages
  !insertmacro MUI_PAGE_WELCOME
  !insertmacro MUI_PAGE_LICENSE "license.txt"
  !insertmacro MUI_PAGE_COMPONENTS
  !insertmacro MUI_PAGE_DIRECTORY
  !insertmacro MUI_PAGE_INSTFILES
  !insertmacro MUI_PAGE_FINISH

  ; Uninstaller pages
  !insertmacro MUI_UNPAGE_CONFIRM
  !insertmacro MUI_UNPAGE_INSTFILES
  
  ; Set UI language
  !insertmacro MUI_LANGUAGE "English"

Install DirectX

Create option to install third-party software like DirectX.

  • SetOutPath: Sets output path and create.
  • File: Extract file(s) to output path.
  • DetailPrint: Add string to details view.
  • ExecWait: Execute program and wait for process to end.
;--------------------------------
; Section - DirectX

  Section "DirectX" DirectX
    SetOutPath "$INSTDIR\Redist"
    File "redist\directx\dxwebsetup.exe"
    DetailPrint "Running DirectX Setup..."
    ExecWait "$INSTDIR\Redist\dxwebsetup.exe"
    DetailPrint "Finished DirectX Setup"
  SectionEnd

Install Captura

This section is hidden from the user with -hidden argument and force check with SectionIn RO. WriteRegStr stores the installation folder and WriteUninstaller creates the uninstaller.

;--------------------------------
; Section - Install App

  Section "-hidden app"
    SectionIn RO
    SetOutPath "$INSTDIR"
    File /r "app\*.*" 
    WriteRegStr HKCU "Software\${NAME}" "" $INSTDIR
    WriteUninstaller "$INSTDIR\Uninstall.exe"
  SectionEnd

Create Shortcut

Create option to create desktop Shortcut for user or not.

;--------------------------------
; Section - Shortcut

  Section "Desktop Shortcut" DeskShort
    CreateShortCut "$DESKTOP\${NAME}.lnk" "$INSTDIR\${APPFILE}"
  SectionEnd

Set Section Description

Set description for each section visible.

;--------------------------------
; Descriptions

  ;Language strings
  LangString DESC_DeskShort ${LANG_ENGLISH} "Create Shortcut on Dekstop."
  LangString DESC_DirectX ${LANG_ENGLISH} "Microsoft DirectX is a collection of application programming interfaces for handling tasks related to multimedia."

  ;Assign language strings to sections
  !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
    !insertmacro MUI_DESCRIPTION_TEXT ${DeskShort} $(DESC_DeskShort)
    !insertmacro MUI_DESCRIPTION_TEXT ${DirectX} $(DESC_DirectX)
  !insertmacro MUI_FUNCTION_DESCRIPTION_END

Remove empty parent directories

RMDirUP is used to recursively delete empty parent folders of a given folder. This function is used with uninstaller. The command RMDir /r «$INSTDIR» cant remove parent folder.

;--------------------------------
; Remove empty parent directories

  Function un.RMDirUP
    !define RMDirUP '!insertmacro RMDirUPCall'

    !macro RMDirUPCall _PATH
          push '${_PATH}'
          Call un.RMDirUP
    !macroend

    ; $0 - current folder
    ClearErrors

    Exch $0
    ;DetailPrint "ASDF - $0\.."
    RMDir "$0\.."

    IfErrors Skip
    ${RMDirUP} "$0\.."
    Skip:

    Pop $0

  FunctionEnd

Remove empty parent directories

This section in called with uninstaller. Removes shortcut and any other associated files. Command RMDir /r «$INSTDIR» does not remove the parent folder there for is function RMDirUP called last for cleanup.

;--------------------------------
; Section - Uninstaller

Section "Uninstall"

  ;Delete Shortcut
  Delete "$DESKTOP\${NAME}.lnk"

  ;Delete Uninstall
  Delete "$INSTDIR\Uninstall.exe"

  ;Delete Folder
  RMDir /r "$INSTDIR"
  ${RMDirUP} "$INSTDIR"

  DeleteRegKey /ifempty HKCU "Software\${NAME}"

SectionEnd

Compile

Last to do is compiling the script and get your setup file. Select setup.nsi then MOUSE + RIGHT-CLICK and Compile NSIS Script. When compiling is finished, Press Test installer

It’s one thing to develop and test a Windows application; it’s quite another to bundle it up into a nice executable that installs correctly on all the different Windows versions that you need to support. I’d like to guide you through the process that I wish I had when I was creating my first installer.

Step 1 – Use your bare hands.

Start by taking your target directory (the one containing your compiled .exe and a bunch of .dll files) and plopping the whole thing onto a Windows machine. Then, manually install any prerequisites, like the particular version of the .NET framework that the app requires. It’s helpful to perform this step on an older platform that’s more likely to contain compatibility issues, e.g. Windows XP.

Now run the executable directly, and make sure it works. If there are problems, the machine may still be missing prerequisites. Double-check that the platform (x86 vs. x64) and .NET framework target of your build match up with the configuration of the machine you’re testing on. An installer won’t fix problems encountered here, so be sure to fix any issues before moving on.

Step 2 – Build it.

Next, we create an actual installer. Visual Studio lets us do this in two easy steps:

  1. Add a new “Visual Studio Installer/Setup Project” to your current solution.
  2. View the file system settings of the new project. Add a new Project Output to the Application Folder, and set it to be the Primary Output of your main project.

That alone is sufficient to build an MSI installer that will copy your project’s output onto the target machine. Other useful settings include adding shortcuts to the Start Menu/desktop, customizing registry settings, and configuring whether the installation applies to all users or not.

<p>Caveat: Visual Studio versions after 2010 seem to build MSIs that choke on Windows XP. No matter the configuration, my installer failed for me on XP with an &#8220;installation interrupted&#8221; message. The <a href=»http://stackoverflow.com/a/26039835″ style=»text-decoration: underline;»>unfortunate workaround</a> involves copying a dll from a Visual Studio 2010 installation over to the newer version&#8217;s directory.</p>

An alternative to Visual Studio is the highly configurable WiX Toolset. With WiX, you specify filenames, registry keys, and other installation information through XML. WiX’s candle and light tools then compile and link that information into an MSI file.

One difficulty I had was that WiX requires every file involved in the installation to be individually specified in the XML. It’s not possible to simply include the entire directory. This is by design. It is possible, however, to automatically generate the XML for a large number of files using another WiX tool called heat.

Step 3 – Bundle it all together.

At this point, we have an MSI that installs our application. In order to have a seamless user experience, we need to bundle that installer along with all of its prerequisites. It’s not possible to add everything to a single MSI file, but with WiX we can write a bootstrapper that chains multiple installation packages together.

In Visual Studio, we can first install the “WiX Toolset” extension and then add a new project to our solution of type “Windows Installer XML/Bootstrapper Project”. Inside the new project, we need to add our chained packages to the auto-generated Bundle.wxs file:

https://gist.github.com/benash/4ec9599c4f00e744f131

The easiest way to add installation items to our chain is to download the needed .msi/.exe files to our project and link to them statically. The downside of this approach is that the resulting bootstrapper may be enormous.

<p>Caveat: For some reason, Windows 7 requires .NET to be installed by enabling it as a &#8220;Windows feature&#8221;. Running a .NET MSI on Windows 7 will fail. To work around the issue, we can <a href=»http://stackoverflow.com/q/18126502″>enable the feature by using Wix to execute dism.exe</a>.</p>

Automatically downloading packages

The other option is to configure our bootstrapper to download and install its own packages. To do this, we need to define our own package group. WiX documents this element thoroughly, but here’s a summary of the information that we’ll need to add:

  • the remote filename and download URL
  • the hash and certificate details of the remote payload (This can be easily generated using the heat tool.)
  • when to install the package, e.g. for a 64-bit package, only if the machine is 64-bit

<p>If we need our bootstrapper to download and install .NET 4.0 or 4.5, we can save some work by using the <a href=»http://wixtoolset.org/documentation/manual/v3/customactions/wixnetfxextension.html» style=»text-decoration: underline;»>WixNetfxExtension</a>, which contains some predefined package groups. E.g. adding <code>&lt;PackageGroupRef Id=&quot;NetFx40Web&quot;/&gt;</code> to our chain will bundle .NET 4.0.</p>

After some work, we might come up with this for .NET 2.0:

https://gist.github.com/benash/d5b49d71b0e264cfdcc2
 

In this article, you will get an overview of Windows Installer packages, what application packaging formats are available, and how to create your first MSI package.

Use the following links to jump to a specific section:

  • Introduction to Application Packaging Formats
  • MSI technology and why it’s still the most popular Windows Installer package type
  • Why is MSI installer recommended?
  • How to create a Windows Installer package for your application?
  • What are other tools for building an application installer?

Introduction to Application Packaging Formats

The .MSI file extension stands for Microsoft Software Installer. It is a Windows Installer format that uses Microsoft’s Windows Installer service to configure installer packages, such as Windows applications or update packages.

Although people are used to .exe installers, many vendors are offering both MSI and EXE on their websites, or even the EXE installers as wrappers over an MSI installation.

While both options offer the same end result, the EXE installation is more commonly used amongst the general public, while MSI installers are more widely used inside companies.

Microsoft also presented MSIX technology in 2018 as an improved version of the AppX package (initially used only for UWP apps).

MSIX is a new universal package format for Windows 10 and Windows 11 apps. It works on desktop, mobile, and other devices, and it includes strong features from MSI, App-V packages, and the Desktop Bridge program.

MSIX offers extended support for Win32 applications, which is the standard desktop applications that we’ve used for years. This particular factor allows packages to leverage all the new advantages and APIs accessible to an MSIX container when packaging and publishing a standard desktop application.

MSI technology and why it’s still the most popular Windows Installer package type

There is no doubt that there are many ways to create an installation package. Let’s take a look at the packaging industry before and after the arrival of MSI technology.

Before MSI Technology — Creating setup applications

Before Windows Installer, software products used various technologies at the application’s setup request — each of them containing specific installation rules.

Some installers were just archives containing the files, and as an installation operation, they only extracted the necessary application files, not configuring further system settings or letting you configure installation sequences.

That’s why it was common to encounter errors during installation. For example, you could find an older version of a file installed on top of a newer version. Certain setups didn’t consider the resources used along with other applications — resulting in compromising the functionality of other applications when installing and uninstalling them.

After the Release of MSI Technology

To mitigate the issues we just mentioned and to implement a set of common rules in the applications’ administration (installing, repairing, uninstalling), Microsoft released in 2000 the Windows Installer service and MSI files.

An MSI package contains all the information Windows Installer needs for installing or uninstalling an application or a software product.

It includes all the details for rolling the graphical interface for the user, which includes the database and the data streams for different parts of the installation. An .msi file can also have one or more transforms (.mst files), internal or external files, needed for the installation.

Moving on, we will go through the benefits of the MSI installer and how to create a Windows Installer package.

Why is MSI installer recommended?

High customization capabilities

The MSI installer became popular due to its high customization capabilities, allowing the creation of Custom Actions that can be placed anywhere in the Standard Sequences. Even standard sequences can have the standard order rearranged to better suit the user’s needs.

Powerful Logs

Another reason why MSI is the recommended approach for the vendors is the ability to create powerful logs. While this might sound boring to the standard user, in a corporate environment, this ability will save countless hours in the debugging process of a failed installation.

Standardization of the command line for the msiexec

The last reason why MSI is the best choice out there is the standardization of the command line for the msiexec. Without standardization, the deployment of a specific software can only be done if proper documentation is available on the vendor’s website, a step which is commonly skipped by software vendors.

MSI Installer

We can go with many reasons why MSI is the preferred choice, and you’ll see that many of the comparisons tilt the balance towards the PROS.
If you want a more in-depth knowledge of the technology, we strongly recommend reading our free MSI Packaging & Virtualization free eBook.

How to create a Windows Installer package for your application?

There are many tools you can use to create MSI packages. However, Advanced Installer offers a quick solution to create MSI packages through its free edition that can be used for both commercial or non-commercial purposes.

While the MSI technology has stuffy documentation which makes it difficult to work with, Advanced Installer comes with a intuitive GUI that automates most of the steps a user takes when building an installation package. Additionally, it saves the user from potential human errors by scanning and repairing the package with a set of industry best practices.

Give Advanced Installer a try with our Advanced Installer FREE edition. Start off on the right foot when creating your first package.

Get started with Advanced Installer Free edition now!

Here’s how you can create an MSI package:

1. Create a project

Let’s assume that we have a simple application executable that only outputs some lines. After launching Advanced Installer, you will be prompted with a dialog where you can choose the type of project you want to create.

Create Advanced Installer Project

  1. Select the “Simple” type.
  2. Uncheck the “Use wizard…” option.
  3. Click on the [ Create Project ] button.
  4. The new project has been created and from now on you start editing it.

2. Add files to the project

Now that the project is created, let’s add the file to it.

1. Go to the “Files and Folders” page by selecting it in the left-side panel. The folders which interest you most are “Application Folder” and “Application Shortcut Folder”.

In the Application Folder, we will place all the necessary files we want to copy on the machine during installation, while in the Application Shortcut folder we can add shortcuts to our applications, help files, or URLs.

2. Now, in the Files and Folders page, click on the [ Add Files ] button and select your files. In our case we added the Sample.exe.

Add Files in Application Folder

3. Create shortcuts to the MSI Installer

Adding a shortcut to your application in the Start Menu makes it easier for users to access it.

To create a shortcut for our Sample.exe, we need to right-click it and select New Shortcut To > Installed file.

The “New File Shortcut” dialog will appear, allowing you to customize the new shortcut.

Customize Shortcut

The new shortcut will be added to the Application Shortcut Folder. That means that this shortcut will be installed in the “Start > All Programs > Product Name” menu of the Target Computer.

4. Build and install the MSI package

To build and install the MSI package, follow these steps:

1. Click on the [ Build ] toolbar button and a “Build Project” dialog will appear, showing you the build evolution.

2. Once the build is complete, run the project by clicking on the [ Run ] toolbar button.

3. A setup wizard will appear that will guide you through the install process of the “story.txt” file.

Build and Run Project

Congratulations! You created your first MSI installer.

Conclusion

MSI packaging is here to stay. Aside from its powerful features, MSI technology is the most popular type of Windows Installer package used by IT professionals when creating a setup package for their applications.

There are quite a few tools available on the market for creating an MSI installer package, and it’s up to you to decide which one suits you the most.

Subscribe to Our Newsletter

Sign up for free and be the first to receive the latest news, videos, exclusive How-Tos, and guides from Advanced Installer.

Popular Articles

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Как зайти в управление дисками на windows 10 через win r
  • Asus u31s драйвера windows 10
  • Компьютер запущен некорректно windows 10 как исправить через биос
  • Windows xp source code torrent
  • Как сделать так чтобы компьютер не входил в спящий режим windows 10