Conceder o identificador de pacote por empacotamento com localização externa

Se você tiver um aplicativo de área de trabalho existente, com seu próprio instalador, há muito pouco que você precisa alterar para se beneficiar do identificador de pacote.

Muitos recursos de extensibilidade do Windows, incluindo tarefas em segundo plano, notificações, blocos dinâmicos, extensões personalizadas de menu de contexto e destinos de compartilhamento, podem ser utilizados por um aplicativo de desktop somente se esse aplicativo tiver a identidade do pacote no runtime. Isso ocorre porque o SO (sistema operacional) precisa identificar o chamador da API correspondente. Consulte Recursos que exigem a identidade do pacote.

Somente os aplicativos empacotados têm a identidade do pacote no runtime. Para definições de aplicativos que são empacotados, não empacotados e empacotados com localização externa, consulte a Visão geral da implantação.

  • No Windows 10, versão 2004 e anteriores, a única maneira de conceder o identificador de pacote a um aplicativo é empacotá-lo em um pacote MSIX assinado (consulte Como criar um pacote MSIX a partir do seu código). Nesse caso, a identidade é especificada no manifesto do pacote e o registro de identidade é realizado pelo pipeline de implantação do MSIX com base nas informações no manifesto. Todo o conteúdo referenciado no manifesto do pacote está presente no pacote MSIX.
  • Mas, a partir de Windows 10, versão 2004, é possível conceder o identificador de pacote a um aplicativo simplesmente criando e registrando um pacote com localização externa com seu aplicativo. Isso o transforma em um aplicativo empacotado, especificamente, um aplicativo empacotado com localização externa. Isso ocorre porque alguns aplicativos da área de trabalho ainda não estão prontos para que todo o conteúdo esteja presente dentro de um pacote MSIX. Portanto, esse suporte permite que esses aplicativos tenham o identificador de pacote, podendo usar os recursos de extensibilidade do Windows que exigem a identidade do pacote. Para obter mais informações em segundo plano, consulte a postagem no blog Identidade, Registro e Ativação de Aplicativos Win32 não empacotados.

Para compilar e registrar um pacote com localização externa (que concede um identificador de pacote ao seu aplicativo), siga estas etapas.

  1. Criar um manifesto de pacote para o pacote com localização externa
  2. Compilar e assinar o pacote com localização externa
  3. Adicionar os metadados do identificador de pacote ao manifesto do aplicativo da área de trabalho
  4. Registrar seu pacote com localização externa em tempo de execução

Conceitos importantes

Os recursos a seguir permitem que aplicativos da área de trabalho não empacotados adquiram um identificador de pacote.

Pacote com localização externa

Um pacote com localização externa contém um manifesto do pacote, mas nenhum outro conteúdo nem binários de aplicativo. O manifesto de um pacote com localização externa pode referenciar arquivos fora do pacote em uma localização externa predeterminada. Conforme mencionado acima, esse suporte permite que aplicativos que ainda não estejam prontos para que todo o conteúdo esteja presente dentro de um pacote MSIX para usar os recursos de extensibilidade do Windows que exigem o identificador de pacote.

Observação

Um aplicativo da área de trabalho que usa um pacote com localização externa não recebe alguns dos benefícios de ser totalmente implantado por um pacote MSIX. Esses benefícios incluem proteção contra adulterações, instalação em uma localização bloqueada e gerenciamento completo pelo sistema operacional na implantação, no runtime e na desinstalação.

Permitindo conteúdo externo

Para dar suporte a pacotes com localização externa, o esquema de manifesto do pacote agora dá suporte a um elemento uap10:AllowExternalContent opcional no elemento Properties. Isso permite que o manifesto do pacote faça referência ao conteúdo fora do pacote, em uma localização específica no disco.

Por exemplo, se você tiver o aplicativo da área de trabalho não empacotado existente que instala o executável do aplicativo e outro conteúdo em C:\Program Files\MyDesktopApp, poderá criar um pacote com localização externa que inclua o elemento uap10:AllowExternalContent no manifesto. Durante o processo de instalação do aplicativo ou na primeira vez em que ele é executado, você pode instalar o pacote com localização externa e declarar C:\Arquivos de Programas\MyDesktopApp\ como a localização externa que o aplicativo usará.

Criar um manifesto de pacote para o pacote com localização externa

Antes de compilar um pacote com localização externa, primeiro você precisa criar um manifesto do pacote (um arquivo chamado AppxManifest.xml) que declara os metadados do identificador de pacote para seu aplicativo da área de trabalho e outros detalhes necessários. A maneira mais fácil de criar um manifesto do pacote para o pacote com localização externa é usar o exemplo abaixo e personalizá-lo para seu aplicativo usando a referência de esquema.

Verifique se o manifesto do pacote inclui estes itens:

  • Um elemento Identity que descreve os atributos de identidade do aplicativo da área de trabalho.
  • Um elemento uap10:AllowExternalContent no elemento Properties. Esse elemento deve receber o valor true, que permite que o manifesto do pacote faça referência ao conteúdo fora do pacote, em uma localização específica no disco. Em uma etapa posterior, você especificará o caminho da localização externa ao registrar o pacote com localização externa a partir do código que é executado em seu instalador ou aplicativo. Qualquer conteúdo que você referencia no manifesto que não está localizado no pacote em si deve ser instalado na localização externa.
  • O atributo MinVersion do elemento TargetDeviceFamily deve ser definido como 10.0.19000.0 ou uma versão posterior.
  • Os atributos TrustLevel=mediumIL e RuntimeBehavior=Win32App do elemento Application declaram que o aplicativo da área de trabalho associado ao pacote com localização externa será executado de maneira semelhante a um aplicativo da área de trabalho não empacotado padrão, sem a virtualização do Registro e do sistema de arquivos e outras alterações de runtime.

O exemplo a seguir mostra o conteúdo completo de um manifesto do pacote com localização externa (AppxManifest.xml). Esse manifesto inclui uma extensão windows.sharetarget, que requer o identificador de pacote.

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

Compilar e assinar o pacote com localização externa

Depois de criar o manifesto do pacote, compile o pacote com localização externa usando a ferramenta MakeAppx.exe no SDK do Windows. Como o pacote com localização externa não contém os arquivos referenciados no manifesto, você precisa especificar a opção /nv, que ignora a validação semântica do pacote.

O exemplo a seguir demonstra como criar um pacote com localização externa na linha de comando.

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

Antes que o pacote com localização externa possa ser instalado com êxito em um computador de destino, você precisa conectá-lo com um certificado confiável no computador de destino. Crie um certificado autoassinado para fins de desenvolvimento e assine o pacote com localização externa usando o SignTool, que está disponível no SDK do Windows.

O exemplo a seguir demonstra como assinar um pacote com localização externa na linha de comando.

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

Adicionar os metadados do identificador de pacote ao manifesto do aplicativo da área de trabalho

Você também precisa incluir um manifesto do aplicativo lado a lado com seu aplicativo da área de trabalho. Confira Manifestos do aplicativo (é o arquivo que faz declarações como reconhecimento de DPI e que está inserido no seu aplicativo .exe durante o build). Nesse arquivo, inclua um elemento msix com atributos que declaram os atributos de identidade do aplicativo. Os valores desses atributos são usados pelo sistema operacional para determinar a identidade do aplicativo quando o executável é iniciado.

O exemplo a seguir mostra um manifesto do aplicativo lado a lado com um elemento 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>

Os atributos do elemento msix precisam corresponder a estes valores no manifesto do pacote para o seu pacote com localização externa:

  • Os atributos packageName e publisher precisam corresponder aos atributos Name e Publisher no elemento Identity do manifesto do pacote, respectivamente.
  • O atributo applicationId precisa corresponder ao atributo Id do elemento Application do manifesto do pacote.

Registrar seu pacote com localização externa em tempo de execução

Para conceder o identificador de pacote ao aplicativo da área de trabalho, ele deve registrar o pacote com localização externa usando o método AddPackageByUriAsync da classe PackageManager. Esse método está disponível do Windows 10, versão 2004, em diante. Adicione código ao aplicativo para registrar o pacote com localização externa quando o aplicativo é executado pela primeira vez ou pode executar o código para registrar o pacote enquanto seu aplicativo da área de trabalho é instalado (por exemplo, se estiver usando o MSI para instalar o aplicativo da área de trabalho, você poderá executar esse código de uma ação personalizada).

O exemplo a seguir demonstra como registrar um pacote com localização externa. Esse código cria um objeto AddPackageOptions que contém o caminho para a localização externa em que o manifesto do pacote pode fazer referência ao conteúdo fora do pacote. Em seguida, o código passa esse objeto para o método AddPackageByUriAsync para registrar o pacote com localização externa. Esse método também recebe a localização do pacote com localização externa assinado como um URI. Para obter um exemplo mais completo, consulte o StartUp.cs arquivo de código no aplicativo de exemplo relacionado (consulte a seção Amostra de aplicativo neste tópico).

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...
    }
}

Aplicativo de exemplo

Confira a amostra SparsePackages para obter um aplicativo de exemplo totalmente funcional que demonstra como conceder um identificador de pacote a um aplicativo da área de trabalho usando um pacote com localização externa. Mais informações sobre como criar e executar o exemplo são fornecidas na postagem de blog Identidade, Registro e Ativação de Aplicativos Win32 não empacotados.

Esse exemplo inclui o seguinte:

  • O código-fonte de um aplicativo do WPF chamado PhotoStoreDemo. Durante a inicialização, o aplicativo verifica se está em execução com uma identidade. Se não estiver em execução com uma identidade, ele registrará o pacote com localização externa e reiniciará o aplicativo. Confira StartUp.cs para ver o código que executa essas etapas.
  • Um manifesto do aplicativo lado a lado chamado PhotoStoreDemo.exe.manifest.
  • Um manifesto do pacote chamado AppxManifest.xml.