Scaricare e installare gli aggiornamenti di pacchetto dallo Store

A partire da Windows 10 versione 1607, puoi usare i metodi della classe StoreContext nello spazio dei nomi Windows.Services.Store per verificare a livello di codice la disponibilità di aggiornamenti di pacchetto per l'app corrente dal Microsoft Store e scaricare e installare i pacchetti aggiornati. Puoi anche eseguire query per trovare i pacchetti che hai contrassegnato come obbligatori nel Centro per i partner e disabilitare la funzionalità nell'app finché non viene installato l'aggiornamento obbligatorio.

Altri metodi StoreContext introdotti in Windows 10 versione 1803 consentono di scaricare e installare gli aggiornamenti di pacchetto automaticamente (senza mostrare l'interfaccia utente di notifica all'utente), disinstallare un pacchetto facoltativo e ottenere informazioni sui pacchetti nella coda di download e installazione per la tua app.

Queste funzionalità ti consentono di mantenere automaticamente aggiornata la base utenti con la versione più recente dell'app, i pacchetti facoltativi e i servizi correlati nello Store.

Scaricare e installare aggiornamenti di pacchetto con l'autorizzazione dell'utente

Questo codice di esempio illustra come usare il metodo GetAppAndOptionalStorePackageUpdatesAsync per individuare tutti gli aggiornamenti di pacchetto disponibili dallo Store e chiamare il metodo RequestDownloadAndInstallStorePackageUpdatesAsync per scaricare e installare gli aggiornamenti. Usando questo metodo per scaricare e installare gli aggiornamenti, il sistema operativo mostra una finestra di dialogo che richiede l'autorizzazione dell'utente prima di scaricare gli aggiornamenti.

Nota

Questi metodi supportano pacchetti obbligatori e pacchetti facoltativi per la tua app. I pacchetti facoltativi sono utili per il contenuto scaricabile, per i componenti aggiuntivi, per dividere app di grandi dimensioni per vincoli di dimensioni o per spedire qualsiasi contenuto aggiuntivo separato dalla tua app principale. Per ottenere l'autorizzazione per inviare un'app che usa i pacchetti facoltativi (compresi i componenti aggiuntivi per il contenuto scaricabile) allo Store, consulta Supporto per gli sviluppatori Windows.

Questo esempio di codice si basa sui presupposti seguenti:

  • Il codice viene eseguito nel contesto di una (Pagina).
  • La pagina contiene un indicatore di stato (ProgressBar) denominato downloadProgressBar per visualizzare lo stato dell'operazione di download.
  • Il file di codice include un'istruzione using per gli spazi dei nomi Windows.Services.Store, Windows.Threading.Tasks e Windows.UI.Popups.
  • L'app è un'app per un singolo utente che viene eseguita solo nel contesto dell'utente che ha avviato l'app. Per un'app multiutente, usa il metodo GetForUser per ottenere un oggetto StoreContext invece del metodo GetDefault.
private StoreContext context = null;

public async Task DownloadAndInstallAllUpdatesAsync()
{
    if (context == null)
    {
        context = StoreContext.GetDefault();
    }

    // Get the updates that are available.
    IReadOnlyList<StorePackageUpdate> updates =
        await context.GetAppAndOptionalStorePackageUpdatesAsync();

    if (updates.Count > 0)
    {
        // Alert the user that updates are available and ask for their consent
        // to start the updates.
        MessageDialog dialog = new MessageDialog(
            "Download and install updates now? This may cause the application to exit.", "Download and Install?");
        dialog.Commands.Add(new UICommand("Yes"));
        dialog.Commands.Add(new UICommand("No"));
        IUICommand command = await dialog.ShowAsync();

        if (command.Label.Equals("Yes", StringComparison.CurrentCultureIgnoreCase))
        {
            // Download and install the updates.
            IAsyncOperationWithProgress<StorePackageUpdateResult, StorePackageUpdateStatus> downloadOperation =
                context.RequestDownloadAndInstallStorePackageUpdatesAsync(updates);

            // The Progress async method is called one time for each step in the download
            // and installation process for each package in this request.
            downloadOperation.Progress = async (asyncInfo, progress) =>
            {
                await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
                () =>
                {
                    downloadProgressBar.Value = progress.PackageDownloadProgress;
                });
            };

            StorePackageUpdateResult result = await downloadOperation.AsTask();
        }
    }
}

Nota

Per scaricare solo gli aggiornamenti di pacchetto disponibili senza installarli, usa il metodo RequestDownloadStorePackageUpdatesAsync.

Visualizzare le informazioni di avanzamento per il download e l'installazione

Quando chiami il metodo RequestDownloadStorePackageUpdatesAsync o RequestDownloadAndInstallStorePackageUpdatesAsync, puoi assegnare un gestore Progress che viene chiamato una sola volta per ogni passaggio nel processo di download (o download e installazione) per ogni pacchetto in questa richiesta. Il gestore riceve un oggetto StorePackageUpdateStatus che fornisce informazioni sul pacchetto di aggiornamento che ha generato la notifica dello stato di avanzamento. L'esempio precedente usa il campo PackageDownloadProgress dell'oggetto StorePackageUpdateStatus per visualizzare lo stato di avanzamento del download e il processo di installazione.

Tieni presente che quando chiami RequestDownloadAndInstallStorePackageUpdatesAsync per scaricare e installare gli aggiornamenti del pacchetto in un'unica operazione, il campo PackageDownloadProgress aumenta da 0,0 a 0,8 durante il processo di download per un pacchetto e in seguito aumenta da 0,8 a 1,0 durante l'installazione. Di conseguenza, se la percentuale, visualizzata nello stato di avanzamento dell'interfaccia utente personalizzata, viene mappata direttamente sul valore del campo PackageDownloadProgress, l'interfaccia utente mostrerà uno stato di avanzamento dell'80% quando il download del pacchetto è terminato e il sistema operativo mostra la finestra di dialogo di installazione. Se vuoi che lo stato di avanzamento dell'interfaccia utente personalizzata mostri il 100% quando il pacchetto è stato scaricato ed è pronto per essere installato, puoi modificare il codice per assegnare 100% allo stato di avanzamento dell'interfaccia utente quando il campo PackageDownloadProgress raggiunge 0,8.

Scaricare e installare automaticamente gli aggiornamenti di pacchetto

A partire da Windows 10 versione 1803, puoi usare i metodi TrySilentDownloadStorePackageUpdatesAsync e TrySilentDownloadAndInstallStorePackageUpdatesAsync per scaricare e installare gli aggiornamenti di pacchetto automaticamente, senza visualizzare l'interfaccia utente di notifica all'utente. L'operazione avrà esito positivo solo se l'utente ha abilitato l'impostazione Aggiorna le app automaticamente nello Store e non usa una rete a consumo. Prima di chiamare questi metodi, puoi verificare la proprietà CanSilentlyDownloadStorePackageUpdates per determinare se queste condizioni sono attualmente soddisfatte.

Questo codice di esempio illustra come usare il metodo GetAppAndOptionalStorePackageUpdatesAsync per individuare tutti gli aggiornamenti di pacchetto disponibili e chiamare i metodi TrySilentDownloadStorePackageUpdatesAsync e TrySilentDownloadAndInstallStorePackageUpdatesAsync per scaricare e installare gli aggiornamenti automaticamente.

Questo esempio di codice si basa sui presupposti seguenti:

  • Il file di codice include un'istruzione using per gli spazi dei nomi Windows.Services.Store e System.Threading.Tasks.
  • L'app è un'app per un singolo utente che viene eseguita solo nel contesto dell'utente che ha avviato l'app. Per un'app multiutente, usa il metodo GetForUser per ottenere un oggetto StoreContext invece del metodo GetDefault.

Nota

I metodi IsNowAGoodTimeToRestartApp, RetryDownloadAndInstallLater e RetryInstallLater chiamati dal codice in questo esempio sono segnaposto che dovranno essere implementati, secondo le esigenze, in base alla progettazione dell'applicazione.

private StoreContext context = null;

public async Task DownloadAndInstallAllUpdatesInBackgroundAsync()
{
    if (context == null)
    {
        context = StoreContext.GetDefault();
    }

    // Get the updates that are available.
    IReadOnlyList<StorePackageUpdate> storePackageUpdates =
        await context.GetAppAndOptionalStorePackageUpdatesAsync();

    if (storePackageUpdates.Count > 0)
    {

        if (!context.CanSilentlyDownloadStorePackageUpdates)
        {
            return;
        }

        // Start the silent downloads and wait for the downloads to complete.
        StorePackageUpdateResult downloadResult =
            await context.TrySilentDownloadStorePackageUpdatesAsync(storePackageUpdates);

        switch (downloadResult.OverallState)
        {
            case StorePackageUpdateState.Completed:
                // The download has completed successfully. At this point, confirm whether your app
                // can restart now and then install the updates (for example, you might only install
                // packages silently if your app has been idle for a certain period of time). The
                // IsNowAGoodTimeToRestartApp method is not implemented in this example, you should
                // implement it as needed for your own app.
                if (IsNowAGoodTimeToRestartApp())
                {
                    await InstallUpdate(storePackageUpdates);
                }
                else
                {
                    // Retry/reschedule the installation later. The RetryInstallLater method is not  
                    // implemented in this example, you should implement it as needed for your own app.
                    RetryInstallLater();
                    return;
                }
                break;
            // If the user cancelled the download or you can't perform the download for some other
            // reason (for example, Wi-Fi might have been turned off and the device is now on
            // a metered network) try again later. The RetryDownloadAndInstallLater method is not  
            // implemented in this example, you should implement it as needed for your own app.
            case StorePackageUpdateState.Canceled:
            case StorePackageUpdateState.ErrorLowBattery:
            case StorePackageUpdateState.ErrorWiFiRecommended:
            case StorePackageUpdateState.ErrorWiFiRequired:
            case StorePackageUpdateState.OtherError:
                RetryDownloadAndInstallLater();
                return;
            default:
                break;
        }
    }
}

private async Task InstallUpdate(IReadOnlyList<StorePackageUpdate> storePackageUpdates)
{
    // Start the silent installation of the packages. Because the packages have already
    // been downloaded in the previous method, the following line of code just installs
    // the downloaded packages.
    StorePackageUpdateResult downloadResult =
        await context.TrySilentDownloadAndInstallStorePackageUpdatesAsync(storePackageUpdates);

    switch (downloadResult.OverallState)
    {
        // If the user cancelled the installation or you can't perform the installation  
        // for some other reason, try again later. The RetryInstallLater method is not  
        // implemented in this example, you should implement it as needed for your own app.
        case StorePackageUpdateState.Canceled:
        case StorePackageUpdateState.ErrorLowBattery:
        case StorePackageUpdateState.OtherError:
            RetryInstallLater();
            return;
        default:
            break;
    }
}

Aggiornamenti di pacchetto obbligatori

Quando crei un invio di pacchetti nel Centro per i partner per un'app per Windows 10 versione 1607 o successive, puoi contrassegnare il pacchetto come obbligatorio specificando la data e l'ora in cui diventerà obbligatorio. Quando questa proprietà è impostata e l'app rileva che l'aggiornamento di pacchetto è disponibile, l'app può determinare se il pacchetto di aggiornamenti è obbligatorio e modificare il proprio comportamento finché non viene installato l'aggiornamento (ad esempio può disabilitare alcune funzionalità).

Nota

Lo stato obbligatorio di un aggiornamento di pacchetto non viene applicato da Microsoft e il sistema operativo non fornisce un'interfaccia utente per indicare agli utenti che deve essere installato un aggiornamento obbligatorio dell'app. È previsto che gli sviluppatori usino l'impostazione obbligatoria per imporre aggiornamenti obbligatori dell'app nel proprio codice.

Per contrassegnare un invio di pacchetti come obbligatorio:

  1. Accedi al Centro per i partner e passa alla pagina di panoramica della tua app.
  2. Fai clic sul nome dell'invio contenente l'aggiornamento di pacchetto che vuoi rendere obbligatorio.
  3. Passa alla pagina Pacchetti per l'invio. Nella parte inferiore della pagina seleziona Rendi obbligatorio questo aggiornamento e quindi scegli il giorno e l'ora in cui l'aggiornamento di pacchetto diventerà obbligatorio. Questa opzione si applica a tutti i pacchetti UWP nell'invio.

Per altre informazioni, vedi Caricare pacchetti di app.

Nota

Se crei un pacchetto in anteprima, puoi contrassegnare i pacchetti come obbligatori usando un'interfaccia utente simile nella pagina Pacchetti per la versione di anteprima. In questo caso, l'aggiornamento di pacchetto obbligatorio si applica solo ai clienti che fanno parte del gruppo di versioni in anteprima.

Esempio di codice per i pacchetti obbligatori

L'esempio di codice seguente illustra come determinare se i pacchetti di aggiornamento sono obbligatori. In genere, è consigliabile eseguire il downgrade dell'esperienza dell'app in modo normale per l'utente se un aggiornamento di pacchetto obbligatorio non è stato scaricato o installato correttamente.

private StoreContext context = null;

// Downloads and installs package updates in separate steps.
public async Task DownloadAndInstallAllUpdatesAsync()
{
    if (context == null)
    {
        context = StoreContext.GetDefault();
    }  

    // Get the updates that are available.
    IReadOnlyList<StorePackageUpdate> updates =
        await context.GetAppAndOptionalStorePackageUpdatesAsync();

    if (updates.Count != 0)
    {
        // Download the packages.
        bool downloaded = await DownloadPackageUpdatesAsync(updates);

        if (downloaded)
        {
            // Install the packages.
            await InstallPackageUpdatesAsync(updates);
        }
    }
}

// Helper method for downloading package updates.
private async Task<bool> DownloadPackageUpdatesAsync(IEnumerable<StorePackageUpdate> updates)
{
    bool downloadedSuccessfully = false;

    IAsyncOperationWithProgress<StorePackageUpdateResult, StorePackageUpdateStatus> downloadOperation =
        this.context.RequestDownloadStorePackageUpdatesAsync(updates);

    // The Progress async method is called one time for each step in the download process for each
    // package in this request.
    downloadOperation.Progress = async (asyncInfo, progress) =>
    {
        await this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
        () =>
        {
            downloadProgressBar.Value = progress.PackageDownloadProgress;
        });
    };

    StorePackageUpdateResult result = await downloadOperation.AsTask();

    switch (result.OverallState)
    {
        case StorePackageUpdateState.Completed:
            downloadedSuccessfully = true;
            break;
        default:
            // Get the failed updates.
            var failedUpdates = result.StorePackageUpdateStatuses.Where(
                status => status.PackageUpdateState != StorePackageUpdateState.Completed);

            // See if any failed updates were mandatory
            if (updates.Any(u => u.Mandatory && failedUpdates.Any(
                failed => failed.PackageFamilyName == u.Package.Id.FamilyName)))
            {
                // At least one of the updates is mandatory. Perform whatever actions you
                // want to take for your app: for example, notify the user and disable
                // features in your app.
                HandleMandatoryPackageError();
            }
            break;
    }

    return downloadedSuccessfully;
}

// Helper method for installing package updates.
private async Task InstallPackageUpdatesAsync(IEnumerable<StorePackageUpdate> updates)
{
    IAsyncOperationWithProgress<StorePackageUpdateResult, StorePackageUpdateStatus> installOperation =
        this.context.RequestDownloadAndInstallStorePackageUpdatesAsync(updates);

    // The package updates were already downloaded separately, so this method skips the download
    // operatation and only installs the updates; no download progress notifications are provided.
    StorePackageUpdateResult result = await installOperation.AsTask();

    switch (result.OverallState)
    {
        case StorePackageUpdateState.Completed:
            break;
        default:
            // Get the failed updates.
            var failedUpdates = result.StorePackageUpdateStatuses.Where(
                status => status.PackageUpdateState != StorePackageUpdateState.Completed);

            // See if any failed updates were mandatory
            if (updates.Any(u => u.Mandatory && failedUpdates.Any(failed => failed.PackageFamilyName == u.Package.Id.FamilyName)))
            {
                // At least one of the updates is mandatory, so tell the user.
                HandleMandatoryPackageError();
            }
            break;
    }
}

// Helper method for handling the scenario where a mandatory package update fails to
// download or install. Add code to this method to perform whatever actions you want
// to take, such as notifying the user and disabling features in your app.
private void HandleMandatoryPackageError()
{
}

Disinstallare i pacchetti facoltativi

A partire da Windows 10 versione 1803, puoi usare il metodo RequestUninstallStorePackageAsync o RequestUninstallStorePackageByStoreIdAsync per disinstallare un pacchetto facoltativo (che comprende un pacchetto con contenuto scaricabile) per l'app corrente. Ad esempio, se hai un'app con contenuto che viene installato tramite pacchetti facoltativi, potresti voler offrire un'interfaccia utente che consente agli utenti di disinstallare i pacchetti facoltativi per liberare spazio su disco.

L'esempio di codice seguente mostra come chiamare il metodo RequestUninstallStorePackageAsync. Questo esempio si basa sui presupposti seguenti:

  • Il file di codice include un'istruzione using per gli spazi dei nomi Windows.Services.Store e System.Threading.Tasks.
  • L'app è un'app per un singolo utente che viene eseguita solo nel contesto dell'utente che ha avviato l'app. Per un'app multiutente, usa il metodo GetForUser per ottenere un oggetto StoreContext invece del metodo GetDefault.
public async Task UninstallPackage(Windows.ApplicationModel.Package package)
{
    if (context == null)
    {
        context = StoreContext.GetDefault();
    }

    var storeContext = StoreContext.GetDefault();
    IAsyncOperation<StoreUninstallStorePackageResult> uninstallOperation =
        storeContext.RequestUninstallStorePackageAsync(package);

    // At this point, you can update your app UI to show that the package
    // is installing.

    uninstallOperation.Completed += (asyncInfo, status) =>
    {
        StoreUninstallStorePackageResult result = uninstallOperation.GetResults();
        switch (result.Status)
        {
            case StoreUninstallStorePackageStatus.Succeeded:
                {
                    // Update your app UI to show the package as uninstalled.
                    break;
                }
            default:
                {
                    // Update your app UI to show that the package uninstall failed.
                    break;
                }
        }
    };
}

Ottenere informazioni sulla coda di download

A partire da Windows 10 versione 1803, puoi usare i metodi GetAssociatedStoreQueueItemsAsync e GetStoreQueueItemsAsync per ottenere informazioni sui pacchetti che si trovano nella coda di download e installazione corrente dallo Store. Questi metodi sono utili se l'app o il gioco supporta pacchetti facoltativi di grandi dimensioni (inclusi contenuti scaricabili) che possono richiedere ore o giorni per il download e l'installazione e vuoi gestire i casi in cui un cliente chiude l'app o il gioco prima che il processo di download e installazione sia completo. Quando il cliente avvia di nuovo l'app o il gioco, il codice può usare questi metodi per ottenere informazioni sullo stato dei pacchetti che sono ancora nella coda di download e installazione, al fine di poter mostrare lo stato di ogni pacchetto al cliente.

L'esempio di codice seguente illustra come chiamare GetAssociatedStoreQueueItemsAsync per ottenere l'elenco degli aggiornamenti di pacchetto in corso per l'app corrente e recuperare informazioni sullo stato di ogni pacchetto. Questo esempio si basa sui presupposti seguenti:

  • Il file di codice include un'istruzione using per gli spazi dei nomi Windows.Services.Store e System.Threading.Tasks.
  • L'app è un'app per un singolo utente che viene eseguita solo nel contesto dell'utente che ha avviato l'app. Per un'app multiutente, usa il metodo GetForUser per ottenere un oggetto StoreContext invece del metodo GetDefault.

Nota

I metodi MarkUpdateInProgressInUI, RemoveItemFromUI, MarkInstallCompleteInUI, MarkInstallErrorInUI e MarkInstallPausedInUI chiamati dal codice in questo esempio sono segnaposto che dovranno essere implementati, a seconda delle esigenze, in base alla progettazione dell'app.

private StoreContext context = null;

private async Task GetQueuedInstallItemsAndBuildInitialStoreUI()
{
    if (context == null)
    {
        context = StoreContext.GetDefault();
    }

    // Get the Store packages in the install queue.
    IReadOnlyList<StoreQueueItem> storeUpdateItems = await context.GetAssociatedStoreQueueItemsAsync();

    foreach (StoreQueueItem storeItem in storeUpdateItems)
    {
        // In this example we only care about package updates.
        if (storeItem.InstallKind != StoreQueueItemKind.Update)
            continue;

        StoreQueueItemStatus currentStatus = storeItem.GetCurrentStatus();
        StoreQueueItemState installState = currentStatus.PackageInstallState;
        StoreQueueItemExtendedState extendedInstallState =
            currentStatus.PackageInstallExtendedState;

        // Handle the StatusChanged event to display current status to the customer.
        storeItem.StatusChanged += StoreItem_StatusChanged;

        switch (installState)
        {
            // Download and install are still in progress, so update the status for this  
            // item and provide the extended state info. The following methods are not
            // implemented in this example; you should implement them as needed for your
            // app's UI.
            case StoreQueueItemState.Active:
                MarkUpdateInProgressInUI(storeItem, extendedInstallState);
                break;
            case StoreQueueItemState.Canceled:
                RemoveItemFromUI(storeItem);
                break;
            case StoreQueueItemState.Completed:
                MarkInstallCompleteInUI(storeItem);
                break;
            case StoreQueueItemState.Error:
                MarkInstallErrorInUI(storeItem);
                break;
            case StoreQueueItemState.Paused:
                MarkInstallPausedInUI(storeItem, installState, extendedInstallState);
                break;
        }
    }
}

private void StoreItem_StatusChanged(StoreQueueItem sender, object args)
{
    StoreQueueItemStatus currentStatus = sender.GetCurrentStatus();
    StoreQueueItemState installState = currentStatus.PackageInstallState;
    StoreQueueItemExtendedState extendedInstallState = currentStatus.PackageInstallExtendedState;

    switch (installState)
    {
        // Download and install are still in progress, so update the status for this  
        // item and provide the extended state info. The following methods are not
        // implemented in this example; you should implement them as needed for your
        // app's UI.
        case StoreQueueItemState.Active:
            MarkUpdateInProgressInUI(sender, extendedInstallState);
            break;
        case StoreQueueItemState.Canceled:
            RemoveItemFromUI(sender);
            break;
        case StoreQueueItemState.Completed:
            MarkInstallCompleteInUI(sender);
            break;
        case StoreQueueItemState.Error:
            MarkInstallErrorInUI(sender);
            break;
        case StoreQueueItemState.Paused:
            MarkInstallPausedInUI(sender, installState, extendedInstallState);
            break;
    }
}