Erteilen der Paketidentität durch Packen mit externem Speicherort

Wenn Sie über eine vorhandene Desktop-App mit eigenem Installationsprogramm verfügen, müssen Sie eine kleine Änderung vornehmen, um die Paketidentität verwenden zu können.

Viele Erweiterungsfunktionen von Windows, darunter Hintergrundaufgaben, Benachrichtigungen, Live-Kacheln, benutzerdefinierte Kontextmenüerweiterungen und Freigabeziele, können von einer Desktop-Anwendung nur verwendet werden, wenn diese Anwendung zur Laufzeit über eine Paketidentität verfügt. Das liegt daran, dass das Betriebssystem den Aufrufer der entsprechenden API identifizieren können muss. Weitere Informationen finden Sie unter Features, für die Paketidentität benötigt wird.

Nur gepackte Apps verfügen zur Laufzeit über eine Paketidentität. Definitionen von gepackten Apps, nicht gepackten Apps und gepackten Apps mit externem Speicherort finden Sie unter Bereitstellungsübersicht.

  • Unter Windows 10 (Version 2004 und früher) können Sie einer App nur eine Paketidentität erteilen, indem Sie sie in ein signiertes MSIX-Paket packen (siehe Erstellen eines MSIX-Pakets aus Ihrem Code). In diesem Fall wird die Identität im Paketmanifest angegeben, und die Identitätsregistrierung wird von der MSIX-Bereitstellungspipeline basierend auf den Informationen im Manifest verarbeitet. Alle Inhalte, auf die im Paketmanifest verwiesen wird, sind im MSIX-Paket vorhanden.
  • Ab Windows 10, Version 2004 können Sie einer App jedoch eine Paketidentität erteilen, indem Sie mit Ihrer App einfach ein Paket mit externem Speicherort erstellen und registrieren. Auf diese Weise wird die App zu einer gepackten App, genauer gesagt eine gepackte App mit externem Speicherort. Das liegt daran, dass einige Desktop-Apps noch nicht bereit sind, ihren gesamten Inhalt in einem MSIX-Paket zu speichern. Durch diese Unterstützung kann Apps eine Paketidentität erteilt werden, was zur Folge hat, dass sie Windows-Erweiterungsfeatures nutzen können, für die eine Paketidentität erforderlich ist. Weitere Hintergrundinformationen finden Sie im Blogbeitrag zum Thema Identität, Registrierung und Aktivierung nicht gepackter Win32-Apps.

Führen Sie die folgenden Schritte aus, um ein Paket mit externem Speicherort zu erstellen und zu registrieren (sodass Ihrer App eine Paketidentität erteilt werden kann).

  1. Erstellen eines Paketmanifests für das Paket mit externem Speicherort
  2. Erstellen und Signieren des Pakets mit externem Speicherort
  3. Hinzufügen der Paketidentität-Metadaten zu deinem Desktopanwendungsmanifest
  4. Registrieren des Pakets mit externem Speicherort zur Laufzeit

Wichtige Konzepte

Mithilfe der folgenden Features können Sie nicht gepackten Desktop-Apps eine Paketidentität erteilen.

Paket mit externem Speicherort

Ein Paket mit externem Speicherort enthält ein Paketmanifest, aber keine anderen App-Binärdateien und -Inhalte. Das Manifest eines Pakets mit externem Speicherort kann auf Dateien außerhalb des Pakets an einem vordefinierten externen Speicherort verweisen. Wie zuvor erwähnt, können Apps, deren gesamte Inhalte noch nicht in einem MSIX-Paket gespeichert werden können, durch diese Unterstützung Windows-Erweiterungsfeatures verwenden, die eine Paketidentität erfordern.

Hinweis

Die vollständige Bereitstellung über ein MSIX-Paket bietet für eine Desktop-App, die ein Paket mit externem Speicherort verwendet, keine Vorteile. Zu diesen Vorteilen gehören der Manipulationsschutz, die Installation an einem gesperrten Speicherort und die vollständige Verwaltung durch das Betriebssystem während Bereitstellung, Runtime und Deinstallation.

Zulassen externer Inhalte

Zur Unterstützung von Paketen mit externem Speicherort unterstützt das Paketmanifestschema nun das optionale Element uap10:AllowExternalContent unter dem Properties-Element. So kann das Paketmanifest auf Inhalte außerhalb des Pakets an einem bestimmten Speicherort auf dem Datenträger verweisen.

Wenn Sie beispielsweise Ihre vorhandene nicht gepackte Desktop-App, die die ausführbare App-Datei und andere Inhalte installiert, unter „C:\Program Files\MyDesktopApp“ speichern, können Sie ein Paket mit externem Speicherort erstellen, das das Element uap10:AllowExternalContent in das Manifest einschließt. Während des Installationsvorgangs für Ihre App oder beim ersten Ausführen Ihrer App können Sie das Paket mit externem Speicherort installieren und „C:\Program Files\MyDesktopApp\“ als externen Speicherort deklarieren, den Ihre App verwenden wird.

Erstellen eines Paketmanifests für das Paket mit externem Speicherort

Bevor Sie ein Paket mit externem Speicherort erstellen können, müssen Sie zunächst ein Paketmanifest (Datei namens „AppxManifest.xml“) erstellen, das Paketidentität-Metadaten für Ihre Desktop-App und andere erforderliche Details deklariert. Die einfachste Möglichkeit zum Erstellen eines Paketmanifests für das Paket mit externem Speicherort besteht darin, das folgende Beispiel zu verwenden und mithilfe des Schemaverweises für Ihre App anzupassen.

Stelle sicher, dass das Paketmanifest die folgenden Elemente enthält:

  • Ein Identity-Element, das die Identitätsattribute für deine Desktop-App beschreibt.
  • Ein uap10:AllowExternalContent-Element unter dem Properties-Element. Diesem Element sollte der Wert true zugewiesen werden, sodass das Paketmanifest auf Inhalte außerhalb des Pakets an einem bestimmten Speicherort auf dem Datenträger verweisen kann. In einem späteren Schritt geben Sie den Pfad des externen Speicherorts an, wenn Sie Ihr Paket mit externem Speicherort über den im Installationsprogramm ausgeführten Code oder über Ihre App registrieren. Alle nicht im Paket selbst befindlichen Inhalte, auf die du im Manifest verweist, sollten am externen Speicherort installiert werden.
  • Das MinVersion-Attribut des TargetDeviceFamily-Elements sollte auf 10.0.19000.0 oder eine spätere Version festgelegt werden.
  • Die Attribute TrustLevel=mediumIL und RuntimeBehavior=Win32App des Application-Elements deklarieren, dass die Desktop-App, die dem Paket mit externem Speicherort zugeordnet ist, ähnlich wie eine nicht gepackte Desktop-Standard-App ausgeführt wird – ohne Registrierung, Dateisystemvirtualisierung und andere Runtimeänderungen.

Das folgende Beispiel zeigt den kompletten Inhalt eines Manifests für ein Paket mit externem Speicherort (AppxManifest.xml). Dieses Manifest enthält eine windows.sharetarget-Erweiterung, die eine Paketidentität erfordert.

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

Erstellen und Signieren des Pakets mit externem Speicherort

Nachdem Sie Ihr Paketmanifest erstellt haben, erstellen Sie unter Verwendung des MakeAppx.exe-Tools im Windows SDK das Paket mit externem Speicherort. Da das Paket mit externem Speicherort nicht die Dateien enthält, auf die im Manifest verwiesen wird, müssen Sie die /nv-Option angeben, die die semantische Validierung für das Paket überspringt.

Das folgende Beispiel veranschaulicht das Erstellen eines Pakets mit externem Speicherort über die Befehlszeile.

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

Bevor das Paket mit externem Speicherort erfolgreich auf einem Zielcomputer installiert werden kann, müssen Sie es mit einem Zertifikat signieren, das auf dem Zielcomputer als vertrauenswürdig eingestuft wird. Sie können ein neues selbstsigniertes Zertifikat zu Entwicklungszwecken erstellen und Ihr Paket mit externem Speicherort mithilfe des Tools SignTool signieren, das im Windows SDK verfügbar ist.

Das folgende Beispiel veranschaulicht das Signieren eines Pakets mit externem Speicherort über die Befehlszeile.

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

Hinzufügen der Paketidentität-Metadaten zu deinem Desktopanwendungsmanifest

Außerdem müssen Sie Ihrer Desktop-App ein paralleles Anwendungsmanifest beifügen. Siehe Anwendungsmanifeste (das ist die Datei, in der Dinge wie DPI deklariert sind, und die während des Buildvorgangs in den .exe Ihrer App eingebettet wird). Fügen Sie in dieser Datei ein msix-Element mit Attributen hinzu, die die Identitätsattribute Ihrer App deklarieren. Die Werte dieser Attribute werden vom Betriebssystem verwendet, um die Identität deiner App zu ermitteln, wenn die ausführbare Datei gestartet wird.

Das folgende Beispiel zeigt ein paralleles Anwendungsmanifest mit einem msix-Element.

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

Die Attribute des msix-Elements müssen mit diesen Werten im Paketmanifest für Ihr Paket mit externem Speicherort übereinstimmen:

  • Die Attribute packageName und publisher müssen mit den Attributen Name und Publisher im Identity-Element deines Paketmanifests identisch sein.
  • Das applicationId-Attribut muss mit dem Id-Attribut des Application-Elements im Paketmanifest identisch sein.

Registrieren des Pakets mit externem Speicherort zur Laufzeit

Um Ihrer Desktop-App eine Paketidentität zu erteilen, muss Ihre App das Paket mit externem Speicherort mithilfe der AddPackageByUriAsync-Methode der PackageManager-Klasse registrieren. Diese Methode steht ab Windows 10, Version 2004, zur Verfügung. Sie können Ihrer App Code hinzufügen, um das Paket mit externem Speicherort zu registrieren, wenn Ihre App zum ersten Mal ausgeführt wird. Sie können jedoch auch Code ausführen, um das Paket zu registrieren, während Ihre Desktop-App installiert wird. (Wenn Sie beispielsweise MSI zum Installieren Ihrer Desktop-App verwenden, können Sie diesen Code über eine benutzerdefinierte Aktion ausführen).

Im folgenden Beispiel wird das Registrieren eines Pakets mit externem Speicherort veranschaulicht. Dieser Code erstellt ein AddPackageOptions-Objekt, das den Pfad zum externen Speicherort enthält, an dem das Paketmanifest auf Inhalte außerhalb des Pakets verweisen kann. Anschließend übergibt der Code dieses Objekt an die AddPackageByUriAsync-Methode, um das Paket mit externem Speicherort zu registrieren. Diese Methode erhält den Speicherort Ihres signierten Pakets mit externem Speicherort als URI. Ein ausführlicheres Beispiel finden Sie in der Codedatei StartUp.cs in der zugehörigen Beispiel-App (siehe Abschnitt Beispiel-App in diesem Artikel).

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

Beispiel-App

Das SparsePackages-Beispiel enthält eine voll funktionsfähige Beispiel-App, die veranschaulicht, wie einer Desktop-App mithilfe eines Pakets mit externem Speicherort eine Paketidentität erteilt wird. Weitere Informationen zum Erstellen und Ausführen des Beispiels finden Sie im Blogbeitrag zum Thema Identität, Registrierung und Aktivierung nicht gepackter Win32-Apps.

Das Beispiel enthält Folgendes:

  • Den Quellcode für eine WPF-App mit dem Namen PhotoStoreDemo. Während des Starts prüft die App, ob sie mit Identität ausgeführt wird. Wenn die Ausführung mit Identität nicht möglich ist, wird das Paket mit externem Speicherort registriert, und die App wird neu gestartet. Den Code, der diese Schritte ausführt, findest du unter StartUp.cs.
  • Ein paralleles Anwendungsmanifest mit dem Namen PhotoStoreDemo.exe.manifest.
  • Ein Paketmanifest mit dem Namen AppxManifest.xml.