应该尝试SilentDownloadAndInstallStorePackageUpdatesAsync重新启动应用程序吗?

问题描述 投票:0回答:2

我正在使用打包为 MSIX 并通过 Microsoft Store 发布的 win32 桌面应用程序进行测试。我正在尝试使用 TrySilentDownloadAndInstallStorePackageUpdatesAsync 来更新应用程序,这似乎确实有效,但在安装更新后立即退出并且不会重新启动应用程序。

MS 文档似乎表明此函数将重新启动应用程序(正如恰当命名的函数 IsNowAGoodTimeToRestartApp 所建议的那样): https://learn.microsoft.com/en-us/windows/uwp/packaging/self-install-package-updates

然而,这不是我所观察到的。调用后的调试语句似乎都没有命中,因此看起来确实正在终止应用程序;它只是没有重新启动它。

寻找替代方案,似乎有一个名为 RegisterApplicationRestart 的旧 win32 API: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-registerapplicationrestart

但它有一个警告: “为了防止周期性重启,系统只会在应用程序运行至少 60 秒时才会重新启动该应用程序。”

这不太理想;我们想要完成的是快速检查更新、安装它们并重新启动,因此在下次运行时应该没有要应用的更新,也不需要重新启动。在这里等待 60 秒违背了快速检查的目的。

有哪些替代方案?有什么方法可以让应用程序在安装 MS Store 更新后重新启动吗?

(顺便说一句:有没有办法在不经过认证过程的情况下测试 MS 商店更新?这可能需要几个小时,这完全消除了写入-构建-测试周期。)。

windows-store-apps desktop msix microsoft-store
2个回答
1
投票

IsNowAGoodTimeToRestartApp
方法只是一个占位符,它代表您需要执行的逻辑来检查应用程序是否准备好安装更新。

StoreContext.TrySilentDownloadAndInstallStorePackageUpdatesAsync 方法不会重新启动应用程序。


0
投票

我也遇到过同样的问题。这真是一场噩梦。我的应用程序也是 win32 桌面应用程序 MSIX 包。我很自信地告诉您,您的应用程序没有尝试重新启动。相反,它崩溃了。如果您阅读合作伙伴中心的运行状况报告,您将看到所有崩溃事件。如果您像我一样,继续上传新版本以使事情正常运行,您可以轻松地将崩溃事件与最新版本联系起来。

经过一番尝试,我发现是对

TrySilentDownloadAndInstallStorePackageUpdatesAsync
的调用导致了崩溃。而问题的解决方案让我感到惊讶。虽然文档说此方法将下载安装更新,但不要相信它!

相反:

  1. 使用
    TrySilentDownloadStorePackageUpdatesAsync
    下载更新
  2. 仅在安装时使用
    TrySilentDownloadAndInstallStorePackageUpdatesAsync

然后没有崩溃!

为了让您的一天更轻松,我将把整个该死的事情发布在这里。应该可以节省您几天的工作时间:

typedef void(*WindowsStoreCallback) (int error);
    
namespace winrt
{
    using namespace winrt;
    using namespace winrt::Windows::Services::Store;
    using namespace winrt::Windows::Foundation;
    using namespace winrt::Windows::Foundation::Collections;
}

winrt::Windows::Foundation::IAsyncAction TrySilentDownloadAndInstallUpdate(WindowsStoreCallback callback)
{
    // return control to caller
    co_await winrt::resume_background();

    // check update
    winrt::IAsyncOperation<winrt::IVectorView<winrt::StorePackageUpdate>> op_check = m_storeContext.GetAppAndOptionalStorePackageUpdatesAsync();
    winrt::IVectorView<winrt::StorePackageUpdate> updates = co_await op_check;
    if (updates.Size() <= 0) {
        callback(E_FAIL);      // handle any other ways to fit your need
        co_return;
    }

    // Download only
    winrt::IAsyncOperationWithProgress<winrt::StorePackageUpdateResult, winrt::StorePackageUpdateStatus> op_download =
        m_storeContext.TrySilentDownloadStorePackageUpdatesAsync(updates);

    bool is_completed = false;
    while (!is_completed) {     // I don't know if the loop is necessary, just added to be safe. The documentation is unclear anyway ...
        winrt::StorePackageUpdateResult result = co_await op_download;
        switch (result.OverallState()) {
        case winrt::StorePackageUpdateState::Pending:
        case winrt::StorePackageUpdateState::Downloading:
        case winrt::StorePackageUpdateState::Deploying:
            ::Sleep(100);
            continue;
        case winrt::StorePackageUpdateState::Completed:
            is_completed = true;
            break;
        case winrt::StorePackageUpdateState::Canceled:
            callback(E_ABORT);
            co_return;

        // all other errors
        case winrt::StorePackageUpdateState::OtherError:
        case winrt::StorePackageUpdateState::ErrorLowBattery:
        case winrt::StorePackageUpdateState::ErrorWiFiRecommended:
        case winrt::StorePackageUpdateState::ErrorWiFiRequired:
        default:
            callback(E_FAIL);
            co_return;
        }
    }

    // (Download) and install
    winrt::IAsyncOperationWithProgress<winrt::StorePackageUpdateResult, winrt::StorePackageUpdateStatus> op_install = 
        m_storeContext.TrySilentDownloadAndInstallStorePackageUpdatesAsync(updates);
    
    while (true) {      // Again, I don't know if the loop is necessary, just to be safe.
        winrt::StorePackageUpdateResult result = co_await op_install;       // Wait for completion
        switch (result.OverallState()) {
        case winrt::StorePackageUpdateState::Pending:
        case winrt::StorePackageUpdateState::Downloading:
        case winrt::StorePackageUpdateState::Deploying:
            break;
        case winrt::StorePackageUpdateState::Completed:
            callback(S_OK);
            co_return;
        case winrt::StorePackageUpdateState::Canceled:
            callback(E_ABORT);
            co_return;

        // all other errors
        case winrt::StorePackageUpdateState::OtherError:
        case winrt::StorePackageUpdateState::ErrorLowBattery:
        case winrt::StorePackageUpdateState::ErrorWiFiRecommended:
        case winrt::StorePackageUpdateState::ErrorWiFiRequired:
        default:
            callback(E_FAIL);
            co_return;
        }

        ::Sleep(100);
    }

    co_return;
}

希望这有帮助。

旁注: 如果有人可以联系 Microsoft 团队,请告诉他们通过提供适用于所有支持的语言的示例代码(直到今天,相应文档中的“示例”类别仍然为空)来让开发人员的日子变得更轻松,并提供一个模拟器测试!仅仅为了测试如此简单的东西而一次又一次地部署是没有乐趣的。你知道,每次更改代码时我都必须部署两次(一次用于代码更改,另一次用于提供更新)。所以我才说这是一场噩梦!

© www.soinside.com 2019 - 2024. All rights reserved.