Предоставление удостоверения пакета путем упаковки с внешним расположением

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

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

Только упакованные приложения имеют удостоверение пакета во время выполнения. Определения приложений, которые упаковываются, распаковываются и упаковываются с внешним расположением, см. в обзоре развертывания.

  • В Windows 10 версии 2004 и более ранних версиях единственным способом предоставления удостоверения пакета приложению является упаковка его в подписанный пакет MSIX (см. статью о создании пакета MSIX из кода). В этом случае удостоверение указывается в манифесте пакета, а регистрация удостоверений обрабатывается конвейером развертывания MSIX на основе сведений в манифесте. Все содержимое, на которое ссылается манифест пакета, содержится в пакете MSIX.
  • Но начиная с Windows 10 версии 2004 вы можете предоставить приложению удостоверение пакета, просто создав и зарегистрировав пакет с внешним расположением в приложении. Это превращает его в упакованое приложение; в частности, упакованное приложение с внешним расположением. Это связано с тем, что некоторые классические приложения еще не готовы к тому, чтобы все их содержимое присутствовало в пакете MSIX. Таким образом, эта поддержка позволяет таким приложениям иметь удостоверение пакета; Таким образом, возможность использовать функции расширяемости Windows, для которых требуется удостоверение пакета. Дополнительные сведения см. в записи блога Identity, Registration and Activation of Non-packaged Win32 Apps.

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

  1. Создание манифеста пакета для пакета с внешним расположением
  2. Создание и подписание пакета с внешним расположением
  3. Добавьте метаданные идентификатора пакета в манифест классического приложения.
  4. Регистрация пакета с внешним расположением во время выполнения

Важные понятия

Следующие функции позволяют распакованным классическим приложениям получать удостоверение пакета.

Упаковка с внешним расположением

Пакет с внешним расположением содержит манифест пакета, но не содержит других двоичных файлов и содержимого приложения. Манифест пакета с внешним расположением может ссылаться на файлы за пределами пакета в предопределенном внешнем расположении. Как упоминалось выше, эта поддержка позволяет приложениям, которые еще не готовы к тому, чтобы все их содержимое присутствовало в пакете MSIX для использования функций расширяемости Windows, требующих удостоверения пакета.

Примечание

Классическое приложение, использующее пакет с внешним расположением, не получает некоторые преимущества полного развертывания с помощью пакета MSIX. К таким преимуществам относятся защита от подделки, установка в заблокированном расположении и полное управление ОС во время развертывания, выполнения и удаления.

Разрешение внешнего содержимого

Для поддержки пакетов с внешним расположением схема манифеста пакета теперь поддерживает необязательный элемент uap10:AllowExternalContent в элементе Properties . Это позволяет манифесту пакета ссылаться на содержимое за пределами пакета в определенном расположении на диске.

Например, если у вас есть существующее непакованное классическое приложение, которое устанавливает исполняемый файл приложения и другое содержимое в папке C:\Program Files\MyDesktopApp, можно создать пакет с внешним расположением, включающим элемент uap10:AllowExternalContent в манифест. Во время установки приложения или при первом запуске приложения можно установить пакет с внешним расположением и объявить C:\Program Files\MyDesktopApp\ как внешнее расположение, которое будет использоваться приложением.

Создание манифеста пакета для пакета с внешним расположением

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

Убедитесь, что манифест пакета содержит следующие элементы:

  • Элемент Identity, описывающий атрибуты идентификатора для классического приложения.
  • Элемент uap10:AllowExternalContent в элементе Properties. Этому элементу следует присвоить значение true, что позволяет манифесту пакета ссылаться на содержимое вне пакета в определенном расположении на диске. На следующем шаге вы укажете путь к внешнему расположению при регистрации пакета с внешним расположением из кода, который выполняется в установщике или приложении. Любое содержимое, на которое вы ссылаетесь в манифесте и которое не находится в самом пакете, должно быть установлено во внешнем расположении.
  • Для атрибута MinVersion элемента TargetDeviceFamily следует задать 10.0.19000.0 или более позднюю версию.
  • Атрибуты TrustLevel=mediumIL и RuntimeBehavior=Win32App элемента Application объявляют, что классическое приложение, связанное с пакетом с внешним расположением, будет выполняться аналогично стандартному неупакованное классическое приложение без виртуализации реестра и файловой системы и других изменений времени выполнения.

В следующем примере показано полное содержимое пакета с манифестом внешнего расположения (AppxManifest.xml). Этот манифест содержит расширение windows.sharetarget, для которого требуется идентификатор пакета.

<?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:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
  xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
  xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
  xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
  IgnorableNamespaces="uap uap2 uap3 rescap desktop uap10">
  <Identity Name="ContosoPhotoStore" ProcessorArchitecture="x64" Publisher="CN=Contoso" Version="1.0.0.0" />
  <Properties>
    <DisplayName>ContosoPhotoStore</DisplayName>
    <PublisherDisplayName>Contoso</PublisherDisplayName>
    <Logo>Assets\storelogo.png</Logo>
    <uap10:AllowExternalContent>true</uap10:AllowExternalContent>
  </Properties>
  <Resources>
    <Resource Language="en-us" />
  </Resources>
  <Dependencies>
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19000.0" MaxVersionTested="10.0.19000.0" />
  </Dependencies>
  <Capabilities>
    <rescap:Capability Name="runFullTrust" />
    <rescap:Capability Name="unvirtualizedResources"/>
  </Capabilities>
  <Applications>
    <Application Id="ContosoPhotoStore" Executable="ContosoPhotoStore.exe" uap10:TrustLevel="mediumIL" uap10:RuntimeBehavior="win32App"> 
      <uap:VisualElements AppListEntry="none" DisplayName="Contoso PhotoStore" Description="Demonstrate photo app" BackgroundColor="transparent" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png">
        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" Square310x310Logo="Assets\LargeTile.png" Square71x71Logo="Assets\SmallTile.png"></uap:DefaultTile>
        <uap:SplashScreen Image="Assets\SplashScreen.png" />
      </uap:VisualElements>
      <Extensions>
        <uap:Extension Category="windows.shareTarget">
          <uap:ShareTarget Description="Send to ContosoPhotoStore">
            <uap:SupportedFileTypes>
              <uap:FileType>.jpg</uap:FileType>
              <uap:FileType>.png</uap:FileType>
              <uap:FileType>.gif</uap:FileType>
            </uap:SupportedFileTypes>
            <uap:DataFormat>StorageItems</uap:DataFormat>
            <uap:DataFormat>Bitmap</uap:DataFormat>
          </uap:ShareTarget>
        </uap:Extension>
      </Extensions>
    </Application>
  </Applications>
</Package>

Создание и подписание пакета с внешним расположением

После создания манифеста пакета создайте пакет с внешним расположением с помощью средстваMakeAppx.exe в windows SDK. Так как пакет с внешним расположением не содержит файлы, на которые ссылается манифест, необходимо указать /nv параметр, который пропускает семантику проверки пакета.

В следующем примере показано, как создать пакет с внешним расположением из командной строки.

MakeAppx.exe pack /d <path to directory that contains manifest> /p <output path>\MyPackage.msix /nv

Перед успешной установкой пакета с внешним расположением на целевом компьютере необходимо подписать его сертификатом, доверенным на целевом компьютере. Вы можете создать самозаверяющий сертификат для целей разработки и подписать пакет с внешним расположением с помощью SignTool, который доступен в Windows SDK.

В следующем примере показано, как подписать пакет с внешним расположением из командной строки.

SignTool.exe sign /fd SHA256 /a /f <path to certificate>\MyCertificate.pfx /p <certificate password> <path to package with external location>\MyPackage.msix

Добавление метаданных идентификатора пакета в манифест классического приложения

Вы также должны включить параллельный манифест приложения с классическим приложением. См. раздел Манифесты приложений (это файл, который объявляет такие вещи, как поддержка DPI, и внедряется в .exe приложения во время сборки). Включите в этот файл элемент msix с атрибутами, которые объявляют атрибуты удостоверения вашего приложения. Значения этих атрибутов использует операционная система для определения идентификатора приложения при запуске исполняемого файла.

В следующем примере показан параллельный манифест приложения с элементом msix.

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="Contoso.PhotoStoreApp"/>
  <msix xmlns="urn:schemas-microsoft-com:msix.v1"
          publisher="CN=Contoso"
          packageName="ContosoPhotoStore"
          applicationId="ContosoPhotoStore"
        />
</assembly>

Атрибуты элемента msix должны соответствовать этим значениям в манифесте пакета с внешним расположением:

  • Атрибуты packageName и publisher должны соответствовать атрибутам Name и Publisher в элементе Identity в манифесте пакета соответственно.
  • Атрибут applicationId должен соответствовать атрибуту Id элемента Application в манифесте пакета.

Регистрация пакета с внешним расположением во время выполнения

Чтобы предоставить удостоверению пакета классическому приложению, приложение должно зарегистрировать пакет с внешним расположением с помощью метода AddPackageByUriAsync класса PackageManager . Этот метод доступен в Windows 10 версии 2004 и более поздних. Вы можете добавить код в приложение, чтобы зарегистрировать пакет с внешним расположением при первом запуске приложения или запустить код, чтобы зарегистрировать пакет во время установки классического приложения (например, если для установки классического приложения используется MSI, можно запустить этот код из настраиваемого действия).

В следующем примере показано, как зарегистрировать пакет с внешним расположением. Этот код создает объект AddPackageOptions, содержащий путь к внешнему расположению, на которое манифест пакета может ссылаться, чтобы указать содержимое вне пакета. Затем код передает этот объект методу AddPackageByUriAsync для регистрации пакета с внешним расположением. Этот метод также получает расположение подписанного пакета с внешним расположением в виде URI. Более полный пример см. StartUp.cs в файле кода в связанном примере приложения (см. раздел "Пример приложения " в этом разделе).

private static bool registerPackageWithExternalLocation(string externalLocation, string pkgPath)
{
    bool registration = false;
    try
    {
        Uri externalUri = new Uri(externalLocation);
        Uri packageUri = new Uri(pkgPath);

        Console.WriteLine("exe Location {0}", externalLocation);
        Console.WriteLine("msix Address {0}", pkgPath);

        Console.WriteLine("  exe Uri {0}", externalUri);
        Console.WriteLine("  msix Uri {0}", packageUri);

        PackageManager packageManager = new PackageManager();

        // Declare use of an external location
        var options = new AddPackageOptions();
        options.ExternalLocationUri = externalUri;

        Windows.Foundation.IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = packageManager.AddPackageByUriAsync(packageUri, options);

        // Other progress and error-handling code omitted for brevity...
    }
}

Пример приложения

Ознакомьтесь с примером SparsePackages для полнофункциональным примером приложения, демонстрирующего предоставление удостоверения пакета классическому приложению с помощью пакета с внешним расположением. Дополнительные сведения о создании и запуске примера приведены в записи блога Identity, Registration and Activation of Non-packaged Win32 Apps.

Этот пример содержит следующие компоненты:

  • Исходный код для приложения WPF с именем PhotoStoreDemo. Во время запуска приложение проверяет, работает ли оно с идентификатором. Если он не работает с удостоверением, он регистрирует пакет с внешним расположением, а затем перезапускает приложение. Дополнительную информацию о коде, который выполняет эти действия, см. в StartUp.cs.
  • Параллельный манифест приложения с именем PhotoStoreDemo.exe.manifest.
  • Манифест пакета с именем AppxManifest.xml.