從 Windows 10 版本 1607 開始,您可以使用 Windows.Services.Store 命名空間中的 StoreContext 類別方法,以程式設計方式檢查Microsoft市集中目前應用程式的套件更新,以及下載並安裝更新的套件。 您也可以查詢您在合作夥伴中心標示為強制性的套件,並停用應用程式中的功能,直到安裝強制更新為止。
Windows 10 版本 1803 中導入的其他 StoreContext 方法可讓您以無訊息方式下載並安裝套件更新(不向使用者顯示通知 UI)、卸載 選用套件,以及取得應用程式下載和安裝佇列中套件的相關信息。
這些功能可協助您使用市集中最新版的應用程式、選用套件和相關服務,自動讓您的使用者基底保持最新狀態。
以使用者的許可權下載並安裝套件更新
此程式代碼範例示範如何使用 GetAppAndOptionalStorePackageUpdatesAsync 方法,從 Store 探索所有可用的套件更新,然後呼叫 RequestDownloadAndInstallStorePackageUpdatesAsync 方法來下載並安裝更新。 使用這個方法來下載和安裝更新時,OS 會顯示對話框,詢問使用者在下載更新之前的許可權。
注意
這些方法支援應用程式所需和選用的套件 。 選用套件適用於可下載的內容 (DLC) 附加元件、分割大型應用程式的大小限制,或將其他內容與核心應用程式分開。 若要取得將使用選用套件的應用程式提交至市集的許可權(包括 DLC 附加元件),請參閱 Windows 開發人員支援。
此程式代碼範例假設:
- 程序代碼會在 Page的內容中執行。
-
Page 包含名為 的
downloadProgressBar,以提供下載作業的狀態。 - 程式代碼檔案具有使用 語句的
、 Windows.Services.Store 、Windows.Threading.Tasks 和Windows.UI.Popups 命名空間。 - 應用程式是單人使用的應用程式,只會在開啟應用程式的使用者內容中執行。 對於 多使用者應用程式,請使用 GetForUser 方法來取得 StoreContext 物件,而不是 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();
}
}
}
注意
若要只下載(但不安裝)可用的套件更新,請使用 RequestDownloadStorePackageUpdatesAsync 方法。
顯示下載並安裝進度資訊
當您呼叫 RequestDownloadStorePackageUpdatesAsync 或 RequestDownloadAndInstallStorePackageUpdatesAsync 方法時,您可以在此要求中對每個套件的下載(或下載和安裝)過程的每個步驟,指定一個 Progress 處理程序。 處理程式會接收 StorePackageUpdateStatus 物件,該物件會提供引發進度通知之更新套件的相關信息。 上述範例會使用 StorePackageUpdateStatus 物件的 PackageDownloadProgress 字段來顯示下載和安裝程式的進度。
請注意,當您呼叫 RequestDownloadAndInstallStorePackageUpdatesAsync 以在單一作業中下載並安裝套件更新時, PackageDownloadProgress 字段會在套件下載程序期間從 0.0 增加到 0.8,然後在安裝期間從 0.8 增加到 1.0。 因此,如果您將自定義進度 UI 中顯示的百分比直接對應至 PackageDownloadProgress 字段的值,當套件完成下載且 OS 顯示安裝對話框時,您的 UI 會顯示 80%。 如果您希望自定義進度 UI 在下載套件並準備好安裝時顯示 100%,您可以在 PackageDownloadProgress 字段達到 0.8 時修改程式代碼,將 100% 指派給您的進度 UI。
以無訊息方式下載並安裝套件更新
從 Windows 10 版本 1803 開始,您可以使用 TrySilentDownloadStorePackageUpdatesAsync 和 TrySilentDownloadAndInstallStorePackageUpdatesAsync 方法來以無訊息方式下載及安裝套件更新,而不向使用者顯示通知 UI。 只有在使用者在市集中啟用了 自動更新應用程式 設定,且使用者所連接的不是計量付費網路時,此作業才會成功。 呼叫這些方法之前,您可以先檢查 CanSilentlyDownloadStorePackageUpdates 屬性,以判斷目前是否符合這些條件。
此程式代碼範例示範如何使用 GetAppAndOptionalStorePackageUpdatesAsync 方法來探索所有可用的套件更新,然後呼叫 TrySilentDownloadStorePackageUpdatesAsync 和 TrySilentDownloadAndInstallStorePackageUpdatesAsync 方法來以無訊息方式下載並安裝更新。
此程式代碼範例假設:
- 程式代碼檔案具有 Windows.Services.Store 和 System.Threading.Tasks 命名空間的 using 語句。
- 應用程式是單人使用的應用程式,只會在開啟應用程式的使用者內容中執行。 對於 多使用者應用程式,請使用 GetForUser 方法來取得 StoreContext 物件,而不是 GetDefault 方法。
注意
此範例中程式代碼所呼叫的 IsNowAGoodTimeToRestartApp、RetryDownloadAndInstallLater 和 RetryInstallLater 方法是佔位符方法,其用途是根據您自己的應用程式設計視需要實作的佔位符方法。
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;
}
}
強制套件更新
當您在合作夥伴中心為以 Windows 10 版本 1607 或更新版本為目標的應用程式建立套件提交時,您可以將 套件標示為必要 ,以及其變成強制性的日期和時間。 當設定此屬性且您的應用程式發現套件更新可供使用時,您的應用程式可以判斷更新套件是否為必要專案,並變更其行為,直到安裝更新為止(例如,您的應用程式可以停用功能)。
注意
套件更新的強制狀態不會由Microsoft強制執行,而且OS不會提供UI來指示用戶必須安裝強制應用程式更新。 開發人員打算使用強制設定,在自己的程式碼中強制執行強制應用程式更新。
若要將套件提交標示為必要:
- 登入 合作夥伴中心 ,並流覽至您應用程式的 [概觀] 頁面。
- 點擊含有您想要設為強制之套件更新的提交的名稱。
- 瀏覽至 套件 頁面以提交。 在此頁面底部附近,選取 [ 強制進行此更新 ],然後選擇套件更新變成強制的日期和時間。 此選項適用於提交中的所有 UWP 套件。
如需詳細資訊,請參閱 上傳應用程式套件。
注意
如果您建立套件發行,可以使用套件頁面上的類似UI,將套件標示為必要。 在此情況下,強制套件更新僅適用於屬於航班群組的客戶。
強制套件的程式代碼範例
下列程式代碼範例示範如何判斷是否有任何更新套件為必要專案。 一般而言,如果強制套件更新未成功下載或安裝,您應該為使用者正常降級您的應用程式體驗。
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()
{
}
卸載選用套件
從 Windows 10 版本 1803 開始,您可以使用 RequestUninstallStorePackageAsync 或 RequestUninstallStorePackageByStoreIdAsync 方法來卸載目前應用程式的 選用套件 (包括 DLC 套件)。 例如,如果您的應用程式具有透過選擇性套件安裝的內容,您可能會想要提供UI,讓使用者卸載選用套件以釋出磁碟空間。
下列程式代碼範例示範如何呼叫 RequestUninstallStorePackageAsync。 此範例假設:
- 程式代碼檔案具有 Windows.Services.Store 和 System.Threading.Tasks 命名空間的 using 語句。
- 應用程式是單人使用的應用程式,只會在開啟應用程式的使用者內容中執行。 對於 多使用者應用程式,請使用 GetForUser 方法來取得 StoreContext 物件,而不是 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;
}
}
};
}
取得下載佇列資訊
從 Windows 10 版本 1803 開始,您可以使用 GetAssociatedStoreQueueItemsAsync 和 GetStoreQueueItemsAsync 方法,從市集取得目前下載和安裝佇列中套件的相關信息。 如果您的應用程式或遊戲支援大型選擇性套件(包括 DLL),可能需要數小時或數天才能下載並安裝,而且您想要在下載和安裝程式完成之前正常處理客戶關閉您的應用程式或遊戲的情況,這些方法就很有用。 當客戶再次啟動您的應用程式或遊戲時,您的程式代碼可以使用這些方法來取得仍在下載和安裝佇列中之套件狀態的相關信息,以便向客戶顯示每個套件的狀態。
下列程式代碼範例示範如何呼叫 GetAssociatedStoreQueueItemsAsync 來取得目前應用程式的進行中套件更新清單,並擷取每個套件的狀態資訊。 此範例假設:
- 程式代碼檔案具有 Windows.Services.Store 和 System.Threading.Tasks 命名空間的 using 語句。
- 應用程式是單人使用的應用程式,只會在開啟應用程式的使用者內容中執行。 對於 多使用者應用程式,請使用 GetForUser 方法來取得 StoreContext 物件,而不是 GetDefault 方法。
注意
此範例中的程式碼所呼叫的 MarkUpdateInProgressInUI、RemoveItemFromUI、MarkInstallCompleteInUI、MarkInstallErrorInUI 和 MarkInstallPausedInUI 方法都是佔位符,這些方法需要根據您自己的應用程式設計視需要實作。
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;
}
}