Freigeben über


Aktualisieren Sie App-Pakete, die nicht im Store veröffentlicht sind, aus Ihrem Code.

Wenn Sie Ihre App als MSIX versenden, können Sie programmgesteuert ein Update Ihrer Anwendung starten. Wenn Sie Ihre App außerhalb des Store bereitstellen, müssen Sie lediglich den Server auf eine neue Version Ihrer App überprüfen und die neue Version installieren. Wie Sie das Update anwenden, hängt davon ab, ob Sie Ihr App-Paket mithilfe einer App-Installer-Datei bereitstellen oder nicht. Um Updates aus Ihrem Code anzuwenden, muss ihr App-Paket die packageManagement Funktion deklarieren. Beachten Sie, dass dies für publisherübergreifende Szenarien erforderlich ist, die Verwaltung Ihrer eigenen App sollte jedoch funktionieren, ohne die Funktion deklarieren zu müssen.

Dieser Artikel enthält Beispiele, die veranschaulichen, wie die packageManagement-Fähigkeit im Paketmanifest deklariert wird und wie ein Update aus Ihrem Code angewendet wird. Im ersten Abschnitt wird erläutert, wie Sie dies tun können, wenn Sie die App-Installer-Datei verwenden, und im zweiten Abschnitt wird beschrieben, wie Sie dies tun können, wenn Sie die App-Installer-Datei nicht verwenden. Im letzten Abschnitt wird erläutert, wie Sie sicherstellen können, dass Ihre App nach anwendung eines Updates neu gestartet wird.

Hinzufügen der PackageManagement-Funktion zum Paketmanifest

Um die PackageManager APIs zu verwenden, muss Ihre App die packageManagementeingeschränkte Funktion im Paketmanifest deklarieren.

<Package>
...

  <Capabilities>
    <rescap:Capability Name="packageManagement" />
  </Capabilities>
  
...
</Package>

Aktualisieren von Paketen, die mithilfe einer App-Installer-Datei bereitgestellt werden

Wenn Sie Ihre Anwendung mithilfe der App Installer-Datei bereitstellen, müssen alle codegesteuerten Updates, die Sie ausführen, die ApIs der App-Installer-Datei verwenden. Dadurch wird sichergestellt, dass die regelmäßigen Aktualisierungen der App-Installer-Dateien weiterhin funktionieren. Zum Intiieren eines app Installer-basierten Updates aus Ihrem Code können Sie PackageManager.AddPackageByAppInstallerFileAsync oder PackageManager.RequestAddPackageByAppInstallerFileAsync verwenden. Sie können überprüfen, ob ein Update mit der Package.CheckUpdateAvailabilityAsync-API verfügbar ist. Nachfolgend sehen Sie Beispielcode:

using Windows.Management.Deployment;

public async void CheckForAppInstallerUpdatesAndLaunchAsync(string targetPackageFullName, PackageVolume packageVolume)
{
    // Get the current app's package for the current user.
    PackageManager pm = new PackageManager();
    Package package = pm.FindPackageForUser(string.Empty, targetPackageFullName);

    PackageUpdateAvailabilityResult result = await package.CheckUpdateAvailabilityAsync();
    switch (result.Availability)
    {
        case PackageUpdateAvailability.Available:
        case PackageUpdateAvailability.Required:
            //Queue up the update and close the current instance
            await pm.AddPackageByAppInstallerFileAsync(
            new Uri("https://trial3.azurewebsites.net/HRApp/HRApp.appinstaller"),
            AddPackageByAppInstallerOptions.ForceApplicationShutdown,
            packageVolume);
            break;
        case PackageUpdateAvailability.NoUpdates:
            // Close AppInstaller.
            await ConsolidateAppInstallerView();
            break;
        case PackageUpdateAvailability.Unknown:
        default:
            // Log and ignore error.
            Logger.Log($"No update information associated with app {targetPackageFullName}");
            // Launch target app and close AppInstaller.
            await ConsolidateAppInstallerView();
            break;
    }
}

Aktualisieren von Paketen, die ohne eine App Installer-Datei bereitgestellt wurden

Prüfen Sie nach Updates auf Ihrem Server

Wenn Sie die App-Installer-Datei nicht zum Bereitstellen Des App-Pakets verwenden, besteht der erste Schritt darin, direkt zu überprüfen, ob eine neue Version Ihrer Anwendung verfügbar ist. Im folgenden Beispiel wird überprüft, ob die Version des Pakets auf einem Server größer ist als die aktuelle Version der App (dieses Beispiel bezieht sich auf einen Testserver zu Demonstrationszwecken).

using Windows.Management.Deployment;

//check for an update on my server
private async void CheckUpdate(object sender, TappedRoutedEventArgs e)
{
    WebClient client = new WebClient();
    Stream stream = client.OpenRead("https://trial3.azurewebsites.net/HRApp/Version.txt");
    StreamReader reader = new StreamReader(stream);
    var newVersion = new Version(await reader.ReadToEndAsync());
    Package package = Package.Current;
    PackageVersion packageVersion = package.Id.Version;
    var currentVersion = new Version(string.Format("{0}.{1}.{2}.{3}", packageVersion.Major, packageVersion.Minor, packageVersion.Build, packageVersion.Revision));

    //compare package versions
    if (newVersion.CompareTo(currentVersion) > 0)
    {
        var messageDialog = new MessageDialog("Found an update.");
        messageDialog.Commands.Add(new UICommand(
            "Update",
            new UICommandInvokedHandler(this.CommandInvokedHandler)));
        messageDialog.Commands.Add(new UICommand(
            "Close",
            new UICommandInvokedHandler(this.CommandInvokedHandler)));
        messageDialog.DefaultCommandIndex = 0;
        messageDialog.CancelCommandIndex = 1;
        await messageDialog.ShowAsync();
    } else
    {
        var messageDialog = new MessageDialog("Did not find an update.");
        await messageDialog.ShowAsync();
    }
}

Hinweis

Der targetPackageFileName steht für den vollständigen Namen der verpackten App. (Beispiel: Contoso.HeadTrax_1.0.0.0_x64__PublisherHash)

Anwenden des Updates

Nachdem Sie festgestellt haben, dass ein Update verfügbar ist, können Sie es in die Warteschlange stellen, um es mithilfe der AddPackageAsync-API herunterzuladen und zur Installation vorzubereiten. Es sollte auch funktionieren, ein optionales Paket zu installieren, solange das Hauptpaket bereits auf dem Gerät installiert ist. Das Update wird angewendet, wenn Ihre App das nächste Mal geschlossen wird. Nachdem die App neu gestartet wurde, ist die neue Version für den Benutzer verfügbar. Nachfolgend sehen Sie Beispielcode:


// Queue up the update and close the current app instance.
private async void CommandInvokedHandler(IUICommand command)
{
    if (command.Label == "Update")
    {
        PackageManager packagemanager = new PackageManager();
        await packagemanager.AddPackageAsync(
            new Uri("https://trial3.azurewebsites.net/HRApp/HRApp.msix"),
            null,
            AddPackageOptions.ForceApplicationShutdown
        );
    }
}

Automatisches Neustarten der App nach einem Update

Wenn es sich bei Ihrer Anwendung um eine UWP-App handelt, sollte das Übergeben von AddPackageByAppInstallerOptions.ForceApplicationShutdown ODER AddPackageOptions.ForceTargetAppShutdown beim Anwenden eines Updates den Neustart der App nach dem Herunterfahren und Update planen. Für Nicht-UWP-Apps müssen Sie RegisterApplicationRestart aufrufen, bevor Sie das Update anwenden.

Sie müssen RegisterApplicationRestart aufrufen, bevor das Herunterfahren Ihrer App beginnt. Nachfolgend finden Sie ein Beispiel für die Verwendung von Interopdiensten zum Aufrufen der systemeigenen Methode in C#:

 // Register the active instance of an application for restart in your Update method
 uint res = RelaunchHelper.RegisterApplicationRestart(null, RelaunchHelper.RestartFlags.NONE);

Ein Beispiel für die Hilfsklasse zum Aufrufen der systemeigenen RegisterApplicationRestart-Methode in C#:

using System;
using System.Runtime.InteropServices;

namespace MyEmployees.Helpers
{
    class RelaunchHelper
    {
        #region Restart Manager Methods
        /// <summary>
        /// Registers the active instance of an application for restart.
        /// </summary>
        /// <param name="pwzCommandLine">
        /// A pointer to a Unicode string that specifies the command-line arguments for the application when it is restarted.
        /// The maximum size of the command line that you can specify is RESTART_MAX_CMD_LINE characters. Do not include the name of the executable
        /// in the command line; this function adds it for you.
        /// If this parameter is NULL or an empty string, the previously registered command line is removed. If the argument contains spaces,
        /// use quotes around the argument.
        /// </param>
        /// <param name="dwFlags">One of the options specified in RestartFlags</param>
        /// <returns>
        /// This function returns S_OK on success or one of the following error codes:
        /// E_FAIL for internal error.
        /// E_INVALIDARG if rhe specified command line is too long.
        /// </returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
        internal static extern uint RegisterApplicationRestart(string pwzCommandLine, RestartFlags dwFlags);
        #endregion Restart Manager Methods

        #region Restart Manager Enums
        /// <summary>
        /// Flags for the RegisterApplicationRestart function
        /// </summary>
        [Flags]
        internal enum RestartFlags
        {
            /// <summary>None of the options below.</summary>
            NONE = 0,

            /// <summary>Do not restart the process if it terminates due to an unhandled exception.</summary>
            RESTART_NO_CRASH = 1,
            /// <summary>Do not restart the process if it terminates due to the application not responding.</summary>
            RESTART_NO_HANG = 2,
            /// <summary>Do not restart the process if it terminates due to the installation of an update.</summary>
            RESTART_NO_PATCH = 4,
            /// <summary>Do not restart the process if the computer is restarted as the result of an update.</summary>
            RESTART_NO_REBOOT = 8
        }
        #endregion Restart Manager Enums

    }
}