Skip to content

Commit 44521e3

Browse files
committed
Move package update monitoring to be explicitly in the Store path
1 parent 6a2762e commit 44521e3

File tree

4 files changed

+134
-109
lines changed

4 files changed

+134
-109
lines changed

src/AppInstallerCLICore/Public/ShutdownMonitoring.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#pragma once
44
#include <Windows.h>
55
#include <AppInstallerProgress.h>
6-
#include <winrt/Windows.ApplicationModel.h>
76
#include <wil/resource.h>
87
#include <memory>
98
#include <mutex>
@@ -61,8 +60,6 @@ namespace AppInstaller::ShutdownMonitoring
6160
wil::unique_event m_messageQueueReady;
6261
wil::unique_hwnd m_windowHandle;
6362
std::thread m_windowThread;
64-
winrt::Windows::ApplicationModel::PackageCatalog m_catalog = nullptr;
65-
decltype(winrt::Windows::ApplicationModel::PackageCatalog{ nullptr }.PackageUpdating(winrt::auto_revoke, nullptr)) m_updatingEvent;
6663
};
6764

6865
// Coordinates shutdown across server components

src/AppInstallerCLICore/ShutdownMonitoring.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,6 @@ namespace AppInstaller::ShutdownMonitoring
7676
m_appShutdownEvent.create();
7777
#endif
7878

79-
if (Runtime::IsRunningInPackagedContext())
80-
{
81-
// Create package update listener
82-
m_catalog = winrt::Windows::ApplicationModel::PackageCatalog::OpenForCurrentPackage();
83-
m_updatingEvent = m_catalog.PackageUpdating(
84-
winrt::auto_revoke, [this](winrt::Windows::ApplicationModel::PackageCatalog, winrt::Windows::ApplicationModel::PackageUpdatingEventArgs)
85-
{
86-
this->StartAppShutdown();
87-
});
88-
}
89-
9079
// Create message only window.
9180
m_messageQueueReady.create();
9281
m_windowThread = std::thread(&TerminationSignalHandler::CreateWindowAndStartMessageLoop, this);

src/AppInstallerCommonCore/MSStore.cpp

Lines changed: 134 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <winget/Runtime.h>
77
#include <AppInstallerFileLogger.h>
88
#include <AppInstallerErrors.h>
9+
#include <winrt/Windows.ApplicationModel.h>
910

1011
namespace AppInstaller::MSStore
1112
{
@@ -176,6 +177,133 @@ namespace AppInstaller::MSStore
176177

177178
return S_FALSE;
178179
}
180+
181+
// Used to detect a signal that a package update is being requested so that we can early out
182+
// on an attempt to update ourself. This is only needed for elevated processes because the
183+
// standard shutdown signals are not sent to elevated processes in the same manner.
184+
struct PackageUpdateMonitor
185+
{
186+
PackageUpdateMonitor()
187+
{
188+
if (Runtime::IsRunningAsAdmin() && Runtime::IsRunningInPackagedContext())
189+
{
190+
m_catalog = winrt::Windows::ApplicationModel::PackageCatalog::OpenForCurrentPackage();
191+
m_updatingEvent = m_catalog.PackageUpdating(
192+
winrt::auto_revoke, [this](winrt::Windows::ApplicationModel::PackageCatalog, winrt::Windows::ApplicationModel::PackageUpdatingEventArgs args)
193+
{
194+
// Deployment always sends a value of 0 before doing any work and a value of 100 when completely done.
195+
constexpr double minProgress = 0;
196+
auto progress = args.Progress();
197+
if (progress > minProgress)
198+
{
199+
m_isUpdating = true;
200+
}
201+
});
202+
}
203+
}
204+
205+
bool IsUpdating() const
206+
{
207+
return m_isUpdating;
208+
}
209+
210+
private:
211+
winrt::Windows::ApplicationModel::PackageCatalog m_catalog = nullptr;
212+
decltype(winrt::Windows::ApplicationModel::PackageCatalog{ nullptr }.PackageUpdating(winrt::auto_revoke, nullptr)) m_updatingEvent;
213+
std::atomic_bool m_isUpdating = false;
214+
};
215+
216+
HRESULT WaitForOperation(const std::wstring& productId, bool isSilentMode, IVectorView<AppInstallItem>& installItems, IProgressCallback& progress, const PackageUpdateMonitor& monitor)
217+
{
218+
auto cancelIfOperationFailed = wil::scope_exit(
219+
[&]()
220+
{
221+
try
222+
{
223+
AppInstallManager installManager;
224+
installManager.Cancel(productId);
225+
}
226+
CATCH_LOG();
227+
});
228+
229+
for (auto const& installItem : installItems)
230+
{
231+
AICLI_LOG(Core, Info, <<
232+
"Started MSStore package execution. ProductId: " << Utility::ConvertToUTF8(installItem.ProductId()) <<
233+
" PackageFamilyName: " << Utility::ConvertToUTF8(installItem.PackageFamilyName()));
234+
235+
if (isSilentMode)
236+
{
237+
installItem.InstallInProgressToastNotificationMode(AppInstallationToastNotificationMode::NoToast);
238+
installItem.CompletedInstallToastNotificationMode(AppInstallationToastNotificationMode::NoToast);
239+
}
240+
}
241+
242+
HRESULT errorCode = S_OK;
243+
244+
// We are aggregating all AppInstallItem progresses into one.
245+
// Averaging every progress for now until we have a better way to find overall progress.
246+
uint64_t overallProgressMax = 100 * static_cast<uint64_t>(installItems.Size());
247+
uint64_t currentProgress = 0;
248+
249+
while (currentProgress < overallProgressMax)
250+
{
251+
currentProgress = 0;
252+
253+
for (auto const& installItem : installItems)
254+
{
255+
const auto& status = installItem.GetCurrentStatus();
256+
currentProgress += static_cast<uint64_t>(status.PercentComplete());
257+
258+
errorCode = status.ErrorCode();
259+
260+
if (!SUCCEEDED(errorCode))
261+
{
262+
return errorCode;
263+
}
264+
}
265+
266+
// It may take a while for Store client to pick up the install request.
267+
// So we show indefinite progress here to avoid a progress bar stuck at 0.
268+
if (currentProgress > 0)
269+
{
270+
progress.OnProgress(currentProgress, overallProgressMax, ProgressType::Percent);
271+
}
272+
273+
if (progress.IsCancelledBy(CancelReason::User))
274+
{
275+
for (auto const& installItem : installItems)
276+
{
277+
installItem.Cancel();
278+
}
279+
}
280+
281+
// If app shutdown then we have 30s to keep installing, keep going and hope for the best.
282+
else if (progress.IsCancelledBy(CancelReason::AppShutdown) || monitor.IsUpdating())
283+
{
284+
for (auto const& installItem : installItems)
285+
{
286+
// Insert spiderman meme.
287+
if (installItem.ProductId() == std::wstring{ s_AppInstallerProductId })
288+
{
289+
AICLI_LOG(Core, Info, << "Asked to shutdown while installing AppInstaller.");
290+
progress.OnProgress(overallProgressMax, overallProgressMax, ProgressType::Percent);
291+
cancelIfOperationFailed.release();
292+
return S_OK;
293+
}
294+
}
295+
}
296+
297+
Sleep(100);
298+
}
299+
300+
if (SUCCEEDED(errorCode))
301+
{
302+
cancelIfOperationFailed.release();
303+
}
304+
305+
return errorCode;
306+
}
179307
}
180308

181309
HRESULT MSStoreOperation::StartAndWaitForOperation(IProgressCallback& progress)
@@ -195,6 +323,8 @@ namespace AppInstaller::MSStore
195323

196324
HRESULT MSStoreOperation::InstallPackage(IProgressCallback& progress)
197325
{
326+
PackageUpdateMonitor monitor;
327+
198328
AppInstallManager installManager;
199329
AppInstallOptions installOptions;
200330

@@ -248,11 +378,13 @@ namespace AppInstaller::MSStore
248378
installOptions).get();
249379
}
250380

251-
return WaitForOperation(installItems, progress);
381+
return WaitForOperation(m_productId, m_isSilentMode, installItems, progress, monitor);
252382
}
253383

254384
HRESULT MSStoreOperation::UpdatePackage(IProgressCallback& progress)
255385
{
386+
PackageUpdateMonitor monitor;
387+
256388
AppInstallManager installManager;
257389
AppUpdateOptions updateOptions;
258390
updateOptions.AllowForcedAppRestart(m_force);
@@ -300,98 +432,6 @@ namespace AppInstaller::MSStore
300432
installItems = winrt::single_threaded_vector(std::move(installItemVector)).GetView();
301433
}
302434

303-
return WaitForOperation(installItems, progress);
304-
}
305-
306-
HRESULT MSStoreOperation::WaitForOperation(IVectorView<AppInstallItem>& installItems, IProgressCallback& progress)
307-
{
308-
auto cancelIfOperationFailed = wil::scope_exit(
309-
[&]()
310-
{
311-
try
312-
{
313-
AppInstallManager installManager;
314-
installManager.Cancel(m_productId);
315-
}
316-
CATCH_LOG();
317-
});
318-
319-
for (auto const& installItem : installItems)
320-
{
321-
AICLI_LOG(Core, Info, <<
322-
"Started MSStore package execution. ProductId: " << Utility::ConvertToUTF8(installItem.ProductId()) <<
323-
" PackageFamilyName: " << Utility::ConvertToUTF8(installItem.PackageFamilyName()));
324-
325-
if (m_isSilentMode)
326-
{
327-
installItem.InstallInProgressToastNotificationMode(AppInstallationToastNotificationMode::NoToast);
328-
installItem.CompletedInstallToastNotificationMode(AppInstallationToastNotificationMode::NoToast);
329-
}
330-
}
331-
332-
HRESULT errorCode = S_OK;
333-
334-
// We are aggregating all AppInstallItem progresses into one.
335-
// Averaging every progress for now until we have a better way to find overall progress.
336-
uint64_t overallProgressMax = 100 * static_cast<uint64_t>(installItems.Size());
337-
uint64_t currentProgress = 0;
338-
339-
while (currentProgress < overallProgressMax)
340-
{
341-
currentProgress = 0;
342-
343-
for (auto const& installItem : installItems)
344-
{
345-
const auto& status = installItem.GetCurrentStatus();
346-
currentProgress += static_cast<uint64_t>(status.PercentComplete());
347-
348-
errorCode = status.ErrorCode();
349-
350-
if (!SUCCEEDED(errorCode))
351-
{
352-
return errorCode;
353-
}
354-
}
355-
356-
// It may take a while for Store client to pick up the install request.
357-
// So we show indefinite progress here to avoid a progress bar stuck at 0.
358-
if (currentProgress > 0)
359-
{
360-
progress.OnProgress(currentProgress, overallProgressMax, ProgressType::Percent);
361-
}
362-
363-
if (progress.IsCancelledBy(CancelReason::User))
364-
{
365-
for (auto const& installItem : installItems)
366-
{
367-
installItem.Cancel();
368-
}
369-
}
370-
371-
// If app shutdown then we have 30s to keep installing, keep going and hope for the best.
372-
else if (progress.IsCancelledBy(CancelReason::AppShutdown))
373-
{
374-
for (auto const& installItem : installItems)
375-
{
376-
// Insert spiderman meme.
377-
if (installItem.ProductId() == std::wstring{ s_AppInstallerProductId })
378-
{
379-
AICLI_LOG(Core, Info, << "Asked to shutdown while installing AppInstaller.");
380-
progress.OnProgress(overallProgressMax, overallProgressMax, ProgressType::Percent);
381-
cancelIfOperationFailed.release();
382-
return S_OK;
383-
}
384-
}
385-
}
386-
387-
Sleep(100);
388-
}
389-
390-
if (SUCCEEDED(errorCode))
391-
{
392-
cancelIfOperationFailed.release();
393-
}
394-
395-
return errorCode;
435+
return WaitForOperation(m_productId, m_isSilentMode, installItems, progress, monitor);
396436
}
397437
}

src/AppInstallerCommonCore/Public/winget/MSStore.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ namespace AppInstaller::MSStore
3939
private:
4040
HRESULT InstallPackage(IProgressCallback& progress);
4141
HRESULT UpdatePackage(IProgressCallback& progress);
42-
HRESULT WaitForOperation(winrt::Windows::Foundation::Collections::IVectorView<winrt::Windows::ApplicationModel::Store::Preview::InstallControl::AppInstallItem>& installItems, IProgressCallback& progress);
4342

4443
MSStoreOperationType m_type;
4544
std::wstring m_productId;

0 commit comments

Comments
 (0)