Pull to refresh

Конвертируем десктопное приложение в appx с помощью Desktop Bridge

Reading time 7 min
Views 13K

С выходом Visual Studio 2017 должна появиться возможность конвертировать существующие .NET/Win32 проекты в Windows Store приложения более комфортным образом.

Впрочем, сейчас для создания appx пакета из .NET приложения совсем не обязательно устанавливать 2017-ую студию. Достаточно установленного пакета SDK для Windows 10 и Visual Studio 2015 с Developer Command Prompt. Что радует, так это то, что после Anniversary Update уже не обязательно скачивать образ десятки и производить установку какого-то стороннего софта, если у вас есть исходный код проекта или исполняемый файл.

Предлагаю создать из .NET приложения appx пакет с помощью Desktop Bridge (ex. Project Centennial).

Как это можно сделать сейчас


Создаем корневую директорию с названием, допустим, WPF2UWPApp. Пусть название вас не смущает, конвертировать можно не только WPF приложения, но и WinForms, Win32 и даже VB6.
В эту папку копируем исполняемый файл приложения и все необходимые библиотеки.

Далее внутри папки создаем файл AppxManifest.xml с подобным содержимым внутри:

Содержимое моего файла AppxManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<Package
   xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
   xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities">
  <Identity Name="WPF2UWPApp"
    ProcessorArchitecture="x86"
    Publisher="CN=AlexejSommer" Version="1.0.0.0" />
  <Properties>
    <DisplayName>Simple WPF UWP App</DisplayName>
    <PublisherDisplayName>Alexej Sommer</PublisherDisplayName>
    <Description>Simple converted from WPF to UWP application</Description>
    <Logo>Assets\SampleAppx.150x150.png</Logo>
  </Properties>
  <Resources>
    <Resource Language="en-us" />
  </Resources>
  <Dependencies>
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.14393.0" MaxVersionTested="10.0.14393.0" />
  </Dependencies>
  <Capabilities>
    <rescap:Capability Name="runFullTrust"/>
  </Capabilities>
  <Applications>
    <Application Id="WPF2UWPApp" Executable="DemoWPFApp.exe" EntryPoint="Windows.FullTrustApplication">
      <uap:VisualElements
       BackgroundColor="#464646"
       DisplayName="Simple WPF UWP App"
       Square150x150Logo="Assets\SampleAppx.150x150.png"
       Square44x44Logo="Assets\SampleAppx.44x44.png"
       Description="Simple converted from WPF to UWP application" >
        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
      </uap:VisualElements>
    </Application>
  </Applications>
</Package>


В манифесте мы используем минимальный набор логотипов. 3 файла SampleAppx.44x44.png, SampleAppx.150x150.png и Wide310x150Logo.png с соответствующими названиям разрешениями должны быть расположены внутри вложенной директории Assets.

Я не собираюсь публиковать это приложение в Store, поэтому в качестве CN издателя указал произвольное значение, а не привязанное к моему аккаунту в Store. Как вы могли заметить я сейчас не инсайдер и использую последний стабильный билд десятки — 10.0.14393.0

Еще раз структура:

Внутри корневой директории находится файл манифеста AppxManifest.xml, файл приложения (в моем случае это файл DemoWPFApp.exe) и другие вспомогательные файлы и библиотеки. Кроме того, внутри находится папка Assets с файлами логотипов. Как минимум это файлы SampleAppx.44x44.png, SampleAppx.150x150.png и Wide310x150Logo.png. После создания структуры и редактирования содержимого файла AppxManifest.xml можно приступать к созданию пакета приложения.

Перед созданием пакета можно протестировать правильность манифеста и прилагаемых файлов, совершив установку приложения в качестве универсального, использовав его манифест. Для тестовой установки открываем PowerShell и выполняем команду (находясь в той же директории, в которой находится и файл AppxManifest)

Add-AppxPackage -Register ".\AppxManifest.xml"

Параметр -Register регистрирует приложение в режиме разработки. Для того чтобы зарегистрировать готовое приложение необходимо использовать еще дополнительно и параметр –DisableDevelopmentMode.

Приложение будет установлено так, как будто оно было установлено из готового appx пакета или скачано из Store. Ссылка на него даже появится в меню «Пуск». Подобное тестирование особенно удобно, если вы добавляете какой-то функционал UWP в .NET приложение и хотите сразу же его протестировать.

Вернемся к упаковке приложения в appx. Для этого открываем Developer Command Prompt. Выполняем следующую команду, которая создает appx файл:

makeappx pack -d "D:\WPF2UWPApp" -p "D:\WPF2UWPApp\WPF2UWPApp.appx"

Копируем файл сертификата из готового проекта или создаем тестовый сертификат как это описывается здесь: Sign an app converted with the Desktop Bridge

Утилита MakeCert находится внутри папки bin SDK. На моей машине это C:\Program Files (x86)\Windows Kits\10\bin\x64 Синтаксис команды таков:

MakeCert.exe -r -h 0 -n "CN=<publisher_name>" -eku 1.3.6.1.5.5.7.3.3 -pe -sv <my.pvk> <my.cer>

Имя publisher CN в манифесте должно соответствовать имени в сертификате. Параметр –eku 1.3.6.1.5.5.7.3.3 это enhanced key usage object identifier (OID), который используется для подписи кода (szOID_PKIX_KP_CODE_SIGNING). Подробную информацию о параметрах MakeCert вы можете найти на ее MSDN страничке. Там же присутствует информация о том, что утилита устарела и вместо нее сейчас рекомендуется использовать PowerShell командлет под названием New-SelfSignedCertificate. Однако, даже в последних примерах использования Desktop Bridge все еще используется MakeCert.

В моем случае команда такая:

MakeCert.exe -r -h 0 -n "CN=AlexejSommer" -eku 1.3.6.1.5.5.7.3.3 -pe -sv alexkey.pvk alexkey.cer

Еще раз обратите внимание, что CN точно такой же, как и в манифесте. В случае запроса пароля можно ввести его или же нажать None. Официальная документация предлагает не использовать пароль.



Далее перемещаем и публичный и приватный ключ в сертификат:

pvk2pfx.exe -pvk alexkey.pvk -spc alexkey.cer -pfx alexcert.pfx

Теперь с помощью SignTool можно подписать сертификатом наш пакет appx. Оба файла (alexcert.pfx и WPF2UWPApp.appx) должны находится в текущей папке:

signtool.exe sign /a /v /fd SHA256 /f "alexcert.pfx" "WPF2UWPApp.appx"

Если вы решили использовать пароль, то добавится параметр /p

signtool.exe sign /a /v /fd SHA256 /f "alexcert.pfx" /p "<пароль>" "WPF2UWPApp.appx"

Если вы сейчас поспешите и попробуете установить appx, то скорее всего при установке вы получите сообщение об ошибке:

Вам необходимо либо установить новый сертификат для этого пакета приложения, либо новый пакет приложения с доверенными сертификатами. Ваш системный администратор или разработчик приложения может помочь в этом. Цепочка сертификатов обработана, но завершена в корневом сертификате, который не является доверенным (0x800B0109)

Дело в том, что:

Чтобы ОС Windows считала сертификат доверенным, сертификат должен располагаться в узле Сертификаты (локальный компьютер) > Доверенные корневые центры сертификации > Сертификаты или Сертификаты (локальный компьютер) > Доверенные лица > Сертификаты.

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

Как установить сертификат в картинках






После установки сертификата можно установить и само приложение, кликнув на appx файл



Лампочка на скриншоте — это логотип моего демо приложения.

Как это можно будет сделать в Visual Studio 2017


На данный момент Visual Studio 2017 находится в стадии Release Candidate. Для автоматического создания пакета appx необходимо установить расширение Desktop to UWP Packaging Project

Открываем существующий проект. Добавляем в решение следующий тип проекта:



Создаем папку PackageLayout. Внутри нее создаем папку Assets. В папку PackageLayout добавляем файл манифеста AppxManifest.xml (файл пока что необходимо создавать вручную). В Assets копируем файлы SampleAppx.44x44.png, SampleAppx.150x150.png и Wide310x150Logo.png.

Не забываем, что необходимо не только скопировать файлы, но и добавить их в проект Visual Studio.

Структура нашего решения получится такой:


В свойствах проекта указываем папку PackageLayout. Если вы все сделали верно, то у вас в поле Start Up Tile появится возможность выбрать из выпадающего списка тайл.



Теперь давайте рассмотрим содержимое файла AppXPackageFileList.xml. По умолчанию оно такое:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!--
  <PropertyGroup>
    <MyProjectOutputPath>C:\MyProject\MyProject\bin</MyProjectOutputPath>
  </PropertyGroup>
  <ItemGroup>
    <LayoutFile Include="$(MyProjectOutputPath)\x86\Debug\MyProject.exe">
      <PackagePath>$(PackageLayout)\MyProject.exe</PackagePath>
    </LayoutFile>
  </ItemGroup>
-->
</Project>

А в результате правок получится что-то вот такое:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <MyProjectOutputPath>$(PackageLayout)\..\..\DemoWPFApp\bin</MyProjectOutputPath>
  </PropertyGroup>
  <ItemGroup>
    <LayoutFile Include="$(MyProjectOutputPath)\Debug\DemoWPFApp.exe">
      <PackagePath>$(PackageLayout)\DemoWPFApp.exe</PackagePath>
    </LayoutFile>
  </ItemGroup>
</Project>

Здесь в качестве MyProjectOutputPath установлена директория из которой будут взяты файлы .NET приложения. Поднявшись на два уровня вверх (именно это означает \..\..\) от PackageLayout находится директория DemoWPFApp внутри которой директория bin. То есть взята папка из второго проекта решения.

Теперь достаточно назначить проект Desktop to UWP Packaging автозагружаемым, запустить проект на выполнение F5 и… на выходе мы должны получить appx. Но пока что не работает. TBD. Ждем релиза.

Как вы можете видеть часть ручной работы пока что все еще осталась. Все еще необходимо создавать вручную структуру директорий, создавать манифест и изменять файл AppXPackageFileList. Надеюсь, что в релизе все это автоматизируется.

Аналогичный англоязычный артикул: Desktop Bridge – Manually converting a desktop application

Альтернативы


Microsoft активно работает с партнерами для того, чтобы была возможность одновременного создания как msi, так и appx инсталляторов. Больше информации вы можете найти по следующим ссылкам:

» FireGiant WIX toolset extensions
» Flexera Software’s InstallShield
» Advanced Installer
» InstallAware APPX Builder

Кроме того, Embarcadero объявила о поддержке Desktop Bridge в своей Embarcadero RAD Studio.



Зачем это нужно?


Приведу несколько очевидных вариантов:

1. Публикация приложения в Store.
2. Application Lifecycle. Универсальные приложения можно устанавливать и удалять множество раз, не опасаясь что они оставят после себя какой-либо мусор.
3. Возможность добавления в .NET приложение функционала, доступного для UWP приложений.
4. Дистрибуция и тестирование через портал устройств. Ops-ы скажут вам спасибо.
Tags:
Hubs:
+15
Comments 10
Comments Comments 10

Articles