Condividi tramite


Scaricare e installare gli aggiornamenti dei pacchetti 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 presenza di aggiornamenti dei pacchetti per l'app corrente da Microsoft Store e scaricare e installare i pacchetti aggiornati. È anche possibile eseguire una query per i pacchetti contrassegnati come obbligatori nel Centro per i partner e disabilitare la funzionalità nell'app fino a quando non viene installato l'aggiornamento obbligatorio.

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

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

Scaricare e installare gli aggiornamenti dei pacchetti con l'autorizzazione dell'utente

Questo esempio di codice illustra come usare il metodo GetAppAndOptionalStorePackageUpdatesAsync per individuare tutti gli aggiornamenti dei pacchetti disponibili dallo Store e quindi chiamare il metodo RequestDownloadAndInstallStorePackageUpdatesAsync per scaricare e installare gli aggiornamenti. Quando si usa questo metodo per scaricare e installare gli aggiornamenti, il sistema operativo visualizza una finestra di dialogo che richiede l'autorizzazione dell'utente prima di scaricare gli aggiornamenti.

Nota

Questi metodi supportano i pacchetti obbligatori e facoltativi per la tua app. I pacchetti facoltativi sono utili per i componenti aggiuntivi DLC (Downloadable Content), dividendo l'app di grandi dimensioni per i vincoli di dimensioni o per la distribuzione di contenuto aggiuntivo separato dall'app principale. Per ottenere l'autorizzazione per inviare un'app che usa pacchetti facoltativi (inclusi i componenti aggiuntivi DLC) allo Store, vedi supporto per sviluppatori Windows.

Questo esempio di codice presuppone:

  • Il codice viene eseguito nel contesto di una pagina .
  • Il page contiene un ProgressBar denominato downloadProgressBar per fornire lo stato per l'operazione di download.
  • Il file di codice include un usando per gli spazi dei nomi Windows.Services.Store, Windows.Threading.Taskse Windows.UI.Popups.
  • L'app è un'app a utente singolo che viene eseguita solo nel contesto dell'utente che ha avviato l'app. Per un'app multiutente , usare il metodo GetForUser per ottenere un oggetto StoreContext anziché il 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 (ma non installare) solo gli aggiornamenti del pacchetto disponibili, usare il metodo RequestDownloadStorePackageUpdatesAsync.

Visualizzare le informazioni sullo stato di avanzamento del download e dell'installazione

Quando chiami il metodo RequestDownloadStorePackageUpdatesAsync o RequestDownloadAndInstallStorePackageUpdatesAsync, puoi assegnare un gestore Progress chiamato una volta per ogni passaggio del 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 di stato. Nell'esempio precedente viene utilizzato il campo PackageDownloadProgress dell'oggetto StorePackageUpdateStat us per visualizzare lo stato di avanzamento del processo di download e installazione.

Tenere presente che quando si chiama RequestDownloadAndInstallStorePackageUpdatesAsync per scaricare e installare gli aggiornamenti dei pacchetti in un'unica operazione, il campo PackageDownloadProgress aumenta da 0,0 a 0,8 durante il processo di download per un pacchetto e quindi aumenta da 0,8 a 1.0 durante l'installazione. Pertanto, se si esegue il mapping della percentuale visualizzata direttamente nell'interfaccia utente dello stato di avanzamento personalizzato al valore del campo PackageDownloadProgress, l'interfaccia utente visualizzerà 80% al termine del download del pacchetto e il sistema operativo visualizza la finestra di dialogo di installazione. Se vuoi che l'interfaccia utente dello stato di avanzamento personalizzato visualizzi 100% quando il pacchetto viene scaricato e pronto per l'installazione, puoi modificare il codice per assegnare 100% all'interfaccia utente di stato quando il campo PackageDownloadProgress raggiunge 0,8.

Scaricare e installare gli aggiornamenti dei pacchetti in modo invisibile all'utente

A partire da Windows 10, versione 1803, puoi usare i metodi TrySilentDownloadStorePackageUpdatesAsync e TrySilentDownloadAndInstallStorePackageUpdatesAsync per scaricare e installare gli aggiornamenti dei pacchetti in modo silenzioso, senza mostrare all'utente un'interfaccia di notifica. Questa operazione avrà esito positivo solo se l'utente ha abilitato l'impostazione Aggiornare automaticamente le app nello Store e l'utente non si trova su una rete a pagamento. Prima di invocare questi metodi, è possibile controllare la proprietà CanSilentlyDownloadStorePackageUpdates per determinare se queste condizioni sono attualmente soddisfatte.

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

Questo esempio di codice presuppone:

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

Nota

I metodi IsNowAGoodTimeToRestartApp, RetryDownloadAndInstallLatere RetryInstallLater chiamati dal codice in questo esempio sono metodi segnaposto che devono essere implementati a seconda del design della vostra app.

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 obbligatori dei pacchetti

Quando crei un invio di pacchetti nel Centro per i partner per un'app destinata a Windows 10, versione 1607 o successiva, puoi contrassegnare il pacchetto come obbligatorio e la data e l'ora in cui diventa obbligatorio. Quando questa proprietà è impostata e l'app rileva che l'aggiornamento del pacchetto è disponibile, l'app può determinare se il pacchetto di aggiornamento è obbligatorio e modificarne il comportamento fino all'installazione dell'aggiornamento(ad esempio, l'app può disabilitare le funzionalità).

Nota

Lo stato obbligatorio di un aggiornamento del pacchetto non viene applicato da Microsoft e il sistema operativo non fornisce un'interfaccia utente per indicare agli utenti che è necessario installare un aggiornamento obbligatorio dell'app. Gli sviluppatori devono usare l'impostazione obbligatoria per applicare gli aggiornamenti obbligatori delle app nel proprio codice.

Per contrassegnare un invio di pacchetto come obbligatorio:

  1. Accedere al Centro per i Partner e passare alla pagina panoramica per l'app.
  2. Fai clic sul nome dell'invio che contiene l'aggiornamento del pacchetto che vuoi rendere obbligatorio.
  3. Vai alla pagina Pacchetti per l'invio. Nella parte inferiore di questa pagina selezionare Rendi obbligatorio questo aggiornamento e quindi scegliere il giorno e l'ora in cui l'aggiornamento del pacchetto diventa obbligatorio. Questa opzione si applica a tutti i pacchetti UWP nell'invio.

Per altre informazioni, vedere 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 in anteprima. In questo caso, l'aggiornamento obbligatorio del pacchetto si applica solo ai clienti che fanno parte del gruppo di test.

Esempio di codice per i pacchetti obbligatori

Nell'esempio di codice seguente viene illustrato come determinare se i pacchetti di aggiornamento sono obbligatori. In genere, è consigliabile degradare l'esperienza dell'app in modo graduale per l'utente se un aggiornamento obbligatorio del pacchetto non viene 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
    // operation 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 pacchetti facoltativi

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

Nell'esempio di codice seguente viene illustrato come chiamare RequestUninstallStorePackageAsync. In questo esempio si presuppone che:

  • Il file di codice include un'istruzione using per i namespace Windows.Services.Store e System.Threading.Tasks.
  • L'app è un'app a utente singolo che viene eseguita solo nel contesto dell'utente che ha avviato l'app. Per un'app multiutente , usare il metodo GetForUser per ottenere un oggetto StoreContext anziché il 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 presenti nella coda di download e installazione corrente dal Microsoft Store. Questi metodi sono utili se l'app o il gioco supporta pacchetti facoltativi di grandi dimensioni (incluse le DLL) che possono richiedere ore o giorni per scaricare e installare e gestire normalmente il caso in cui un cliente chiude l'app o il gioco prima del completamento del processo di download e installazione. Quando il cliente avvia nuovamente l'app o il gioco, il codice può usare questi metodi per ottenere informazioni sullo stato dei pacchetti ancora presenti nella coda di download e installazione in modo da poter visualizzare lo stato di ogni pacchetto al cliente.

L'esempio di codice seguente illustra come chiamare GetAssociatedStoreQueueItemsAsync per ottenere l'elenco degli aggiornamenti dei pacchetti in corso per l'app corrente e recuperare le informazioni sullo stato per ogni pacchetto. In questo esempio si presuppone che:

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

Nota

I MarkUpdateInProgressInUI, RemoveItemFromUI, MarkInstallCompleteInUI, MarkInstallErrorInUIe i metodi di MarkInstallPausedInUI chiamati dal codice in questo esempio sono metodi segnaposto che devono essere implementati in base alla progettazione della propria 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;
    }
}