summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOliver Wolff <oliver.wolff@qt.io>2017-03-23 13:28:39 +0100
committerOliver Wolff <oliver.wolff@qt.io>2017-03-27 06:45:53 +0000
commit7b2f97700b8822abb8428ac1315f34fcaf4a6d5d (patch)
tree2eb176b14a03e0ec7dabdf7f23ecc499840ab6fd
parent39eff1d807dcd5f601c9d3386e2ed75d561a2fcb (diff)
downloadqttools-7b2f97700b8822abb8428ac1315f34fcaf4a6d5d.tar.gz
winrtrunner: Fix waiting for local package (un-)installation
Debugging did not work on some machines as the waiting loop used in qlocalappxengine was not implemented properly. Instead of relying on an undocumented return value of GetResults we register a callback that is triggered when the deployment operation is finished and trigger an event inside that callback in order to avoid a busy loop. Task-number: QTCREATORBUG-17907 Change-Id: I5d2211cfabb71592efa520cf53ad84facf79a4df Reviewed-by: David Schulz <david.schulz@qt.io> Reviewed-by: Maurice Kalinowski <maurice.kalinowski@qt.io> (cherry picked from commit 3947d229cb8ed8dde5ab72708a4a149ac6d83cae)
-rw-r--r--src/winrtrunner/appxlocalengine.cpp74
1 files changed, 64 insertions, 10 deletions
diff --git a/src/winrtrunner/appxlocalengine.cpp b/src/winrtrunner/appxlocalengine.cpp
index 2c3c0dd66..09615ff58 100644
--- a/src/winrtrunner/appxlocalengine.cpp
+++ b/src/winrtrunner/appxlocalengine.cpp
@@ -60,6 +60,9 @@ using namespace ABI::Windows::Management::Deployment;
using namespace ABI::Windows::ApplicationModel;
using namespace ABI::Windows::System;
+typedef IAsyncOperationWithProgressCompletedHandler<DeploymentResult *, DeploymentProgress> DeploymentResultHandler;
+typedef IAsyncOperationWithProgress<DeploymentResult *, DeploymentProgress> DeploymentOperation;
+
QT_USE_NAMESPACE
// Set a break handler for gracefully breaking long-running ops
@@ -378,7 +381,7 @@ bool AppxLocalEngine::installPackage(IAppxManifestReader *reader, const QString
hr = d->uriFactory->CreateUri(hStringFromQString(nativeFilePath), &uri);
RETURN_FALSE_IF_FAILED("Failed to create an URI for the package");
- ComPtr<IAsyncOperationWithProgress<DeploymentResult *, DeploymentProgress>> deploymentOperation;
+ ComPtr<DeploymentOperation> deploymentOperation;
if (addInsteadOfRegister) {
hr = d->packageManager->AddPackageAsync(uri.Get(), NULL, DeploymentOptions_None,
&deploymentOperation);
@@ -390,13 +393,41 @@ bool AppxLocalEngine::installPackage(IAppxManifestReader *reader, const QString
RETURN_FALSE_IF_FAILED("Failed to start package registration");
}
+ HANDLE ev = CreateEvent(NULL, FALSE, FALSE, NULL);
+ hr = deploymentOperation->put_Completed(Callback<DeploymentResultHandler>([ev](DeploymentOperation *, AsyncStatus) {
+ SetEvent(ev);
+ return S_OK;
+ }).Get());
+ RETURN_FALSE_IF_FAILED("Could not register deployment completed callback.");
+ DWORD ret = WaitForSingleObjectEx(ev, 15000, FALSE);
+ CloseHandle(ev);
+ if (ret != WAIT_OBJECT_0) {
+ if (ret == WAIT_TIMEOUT)
+ qCWarning(lcWinRtRunner) << "Deployment did not finish within 15 seconds.";
+ else
+ qCWarning(lcWinRtRunner) << "Deployment finished event was not triggered.";
+ return false;
+ }
+
+ ComPtr<IAsyncInfo> asyncInfo;
+ hr = deploymentOperation.As(&asyncInfo);
+ RETURN_FALSE_IF_FAILED("Failed to cast deployment operation to info.");
+ AsyncStatus status;
+ hr = asyncInfo->get_Status(&status);
+ RETURN_FALSE_IF_FAILED("Failed to retrieve deployment operation's status.");
+
+ if (status != Completed) {
+ qCWarning(lcWinRtRunner) << "Deployment operation did not succeed.";
+ return false;
+ }
+
ComPtr<IDeploymentResult> results;
- while ((hr = deploymentOperation->GetResults(&results)) == E_ILLEGAL_METHOD_CALL)
- Sleep(1);
+ hr = deploymentOperation->GetResults(&results);
+ RETURN_FALSE_IF_FAILED("Failed to retrieve package registration results.");
HRESULT errorCode;
hr = results->get_ExtendedErrorCode(&errorCode);
- RETURN_FALSE_IF_FAILED("Failed to retrieve package registration results.");
+ RETURN_FALSE_IF_FAILED("Failed to retrieve extended error code.");
if (FAILED(errorCode)) {
HString errorText;
@@ -462,17 +493,40 @@ bool AppxLocalEngine::remove()
qCDebug(lcWinRtRunner) << __FUNCTION__;
// ### TODO: use RemovePackageWithOptions to preserve previous state when re-installing
- ComPtr<IAsyncOperationWithProgress<DeploymentResult *, DeploymentProgress>> deploymentOperation;
+ ComPtr<DeploymentOperation> deploymentOperation;
HRESULT hr = d->packageManager->RemovePackageAsync(hStringFromQString(d->packageFullName), &deploymentOperation);
RETURN_FALSE_IF_FAILED("Unable to start package removal");
- ComPtr<IDeploymentResult> results;
- while ((hr = deploymentOperation.Get()->GetResults(&results)) == E_ILLEGAL_METHOD_CALL)
- Sleep(1);
+ HANDLE ev = CreateEvent(NULL, FALSE, FALSE, NULL);
+ hr = deploymentOperation->put_Completed(Callback<DeploymentResultHandler>([ev](DeploymentOperation *, AsyncStatus) {
+ SetEvent(ev);
+ return S_OK;
+ }).Get());
+ RETURN_FALSE_IF_FAILED("Could not register deployment completed callback.");
+ DWORD ret = WaitForSingleObjectEx(ev, 15000, FALSE);
+ CloseHandle(ev);
+ if (ret != WAIT_OBJECT_0) {
+ if (ret == WAIT_TIMEOUT)
+ qCWarning(lcWinRtRunner) << "Deployment did not finish within 15 seconds.";
+ else
+ qCWarning(lcWinRtRunner) << "Deployment finished event was not triggered.";
+ return false;
+ }
- RETURN_FALSE_IF_FAILED("Unable to remove package");
+ ComPtr<IAsyncInfo> asyncInfo;
+ hr = deploymentOperation.As(&asyncInfo);
+ RETURN_FALSE_IF_FAILED("Failed to cast deployment operation.");
- return SUCCEEDED(hr);
+ AsyncStatus status;
+ hr = asyncInfo->get_Status(&status);
+ RETURN_FALSE_IF_FAILED("Failed to retrieve deployment operation's status.");
+
+ if (status != Completed) {
+ qCWarning(lcWinRtRunner) << "Unable to remove package.";
+ return false;
+ }
+
+ return true;
}
bool AppxLocalEngine::start()