Memperbarui paket aplikasi yang diterbitkan non-Store dari kode Anda

Saat mengirim aplikasi sebagai MSIX, Anda dapat memulai pembaruan aplikasi secara terprogram. Jika Anda menyebarkan aplikasi di luar Toko, yang perlu Anda lakukan adalah memeriksa server Anda untuk versi baru aplikasi Anda dan menginstal versi baru. Cara Anda menerapkan pembaruan bergantung pada apakah Anda menyebarkan paket aplikasi menggunakan file Penginstal Aplikasi atau tidak. Untuk menerapkan pembaruan dari kode Anda, paket aplikasi Anda harus mendeklarasikan packageManagement kemampuan. Perhatikan bahwa ini diperlukan untuk skenario lintas penerbit, tetapi mengelola aplikasi Anda sendiri harus berfungsi tanpa harus mendeklarasikan kemampuan.

Artikel ini menyediakan contoh yang menunjukkan cara mendeklarasikan packageManagement kemampuan dalam manifes paket Anda dan cara menerapkan pembaruan dari kode Anda. Bagian pertama melihat cara melakukan ini jika Anda menggunakan file Penginstal Aplikasi dan bagian kedua adalah tentang cara melakukannya saat tidak menggunakan file Penginstal Aplikasi. Bagian terakhir melihat cara memastikan aplikasi Anda dimulai ulang setelah pembaruan diterapkan.

Menambahkan Kemampuan PackageManagement ke manifes paket Anda

Untuk menggunakan PackageManager API, aplikasi Anda harus mendeklarasikan packageManagementkemampuan terbatas dalam manifes paket Anda.

<Package>
...

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

Memperbarui paket yang disebarkan menggunakan file Penginstal Aplikasi

Jika Anda menyebarkan aplikasi menggunakan file Penginstal Aplikasi, setiap pembaruan berbasis kode yang Anda lakukan harus menggunakan API file Penginstal Aplikasi. Melakukannya memastikan bahwa pembaruan file Penginstal Aplikasi reguler Anda akan terus berfungsi. Untuk menginisiasi pembaruan berbasis Penginstal Aplikasi dari kode Anda, Anda dapat menggunakan PackageManager.AddPackageByAppInstallerFileAsync atau PackageManager.RequestAddPackageByAppInstallerFileAsync. Anda dapat memeriksa apakah pembaruan tersedia menggunakan PACKAGE.CheckUpdateAvailabilityAsync API. Di bawah ini adalah contoh kode:

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

Memperbarui paket yang disebarkan tanpa file Penginstal Aplikasi

Memeriksa pembaruan di server Anda

Jika Anda tidak menggunakan file Penginstal Aplikasi untuk menyebarkan paket aplikasi Anda, langkah pertama adalah langsung memeriksa apakah versi baru aplikasi Anda tersedia. Contoh berikut memeriksa untuk melihat versi paket di server lebih besar dari versi aplikasi saat ini (contoh ini mengacu pada server pengujian untuk tujuan demonstrasi).

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();
    }
}

Catatan

targetPackageFileName perwakilan dari nama lengkap aplikasi yang dipaketkan. (Contoh: Contoso.HeadTrax_1.0.0.0_x64__PublisherHash)

Menerapkan pembaruan

Setelah menentukan bahwa pembaruan tersedia, Anda dapat mengantrekannya untuk diunduh dan diinstal menggunakan ADDPackageAsync API. Ini juga harus berfungsi untuk menginstal paket opsional selama paket utama sudah diinstal pada perangkat. Pembaruan akan diterapkan saat aplikasi Anda dimatikan di lain waktu. Setelah aplikasi dimulai ulang, versi baru akan tersedia untuk pengguna. Di bawah ini adalah contoh kode:


// 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
        );
    }
}

Memulai ulang aplikasi anda secara otomatis setelah pembaruan

Jika aplikasi Anda adalah aplikasi UWP, meneruskan AddPackageByAppInstallerOptions.ForceApplicationShutdown ATAU AddPackageOptions.ForceTargetAppShutdown saat menerapkan pembaruan harus menjadwalkan aplikasi untuk memulai ulang setelah pematian + pembaruan. Untuk aplikasi non-UWP, Anda perlu memanggil RegisterApplicationRestart sebelum menerapkan pembaruan.

Anda harus memanggil RegisterApplicationRestart sebelum aplikasi mulai dimatikan. Di bawah ini adalah contoh melakukannya menggunakan layanan interop untuk memanggil metode asli di C#:

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

Contoh kelas pembantu untuk memanggil metode RegisterApplicationRestart asli di 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

    }
}