summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaurice Kalinowski <maurice.kalinowski@qt.io>2016-07-20 12:42:12 +0200
committerMaurice Kalinowski <maurice.kalinowski@qt.io>2016-07-20 14:22:32 +0000
commitfa17fe6d16891a786dfa457a3c13856ebe74925f (patch)
tree3a850da005f3076895a08de256cab0d67918ce97
parentc24403b1dbe8d1b7bc27e2d1e11fd5cddd4ae1b9 (diff)
winrtrunner: Add support for installing packages
So far winrtrunner was only capable of creating a package manually, not to specify a package to install. This can be very helpful for testing purposes. Change-Id: Idecbea3c3413662a1f42f60fec60832eac7e7626 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
-rw-r--r--src/winrtrunner/appxengine.cpp87
-rw-r--r--src/winrtrunner/appxengine_p.h1
-rw-r--r--src/winrtrunner/appxphoneengine.cpp39
3 files changed, 80 insertions, 47 deletions
diff --git a/src/winrtrunner/appxengine.cpp b/src/winrtrunner/appxengine.cpp
index c74f7c4b4..dfdd7d0db 100644
--- a/src/winrtrunner/appxengine.cpp
+++ b/src/winrtrunner/appxengine.cpp
@@ -315,7 +315,7 @@ bool AppxEngine::getManifestFile(const QString &fileName, QString *manifest)
}
// If it looks like an executable, check that manifest is next to it
- if (fileName.endsWith(QStringLiteral(".exe"))) {
+ if (fileName.endsWith(QLatin1String(".exe"))) {
QDir appDir = QFileInfo(fileName).absoluteDir();
QString manifestFileName = appDir.absoluteFilePath(QStringLiteral("AppxManifest.xml"));
if (!QFile::exists(manifestFileName)) {
@@ -328,7 +328,11 @@ bool AppxEngine::getManifestFile(const QString &fileName, QString *manifest)
return true;
}
- // TODO: handle already-built package as well
+ if (fileName.endsWith(QLatin1String(".appx"))) {
+ // For existing appx packages the manifest reader will be
+ // instantiated later.
+ return true;
+ }
qCWarning(lcWinRtRunner) << "Appx: unable to determine manifest for" << fileName << ".";
return false;
@@ -375,12 +379,6 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd)
d->pid = -1;
d->exitCode = UINT_MAX;
- if (!getManifestFile(runner->app(), &d->manifest)) {
- qCWarning(lcWinRtRunner) << "Unable to determine manifest file from" << runner->app();
- d->hasFatalError = true;
- return;
- }
-
HRESULT hr;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Uri).Get(),
IID_PPV_ARGS(&d->uriFactory));
@@ -390,28 +388,57 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd)
IID_IAppxFactory, &d->packageFactory);
CHECK_RESULT_FATAL("Failed to instantiate package factory.", return);
- ComPtr<IStream> manifestStream;
- hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream);
- CHECK_RESULT_FATAL("Failed to open manifest stream.", return);
-
- ComPtr<IAppxManifestReader> manifestReader;
- hr = d->packageFactory->CreateManifestReader(manifestStream.Get(), &manifestReader);
- if (FAILED(hr)) {
- qCWarning(lcWinRtRunner).nospace() << "Failed to instantiate manifest reader. (0x"
- << QByteArray::number(hr, 16).constData()
- << ' ' << qt_error_string(hr) << ')';
- // ### TODO: read detailed error from event log directly
- if (hr == APPX_E_INVALID_MANIFEST) {
- qCWarning(lcWinRtRunner) << "More information on the error can "
- "be found in the event log under "
- "Microsoft\\Windows\\AppxPackagingOM";
+ bool existingPackage = runner->app().endsWith(QLatin1String(".appx"));
+
+ if (existingPackage) {
+ ComPtr<IStream> appxStream;
+ hr = SHCreateStreamOnFile(wchar(runner->app()), STGM_READ, &appxStream);
+ CHECK_RESULT_FATAL("Failed to open appx stream.", return);
+
+ ComPtr<IAppxPackageReader> packageReader;
+ hr = d->packageFactory->CreatePackageReader(appxStream.Get(), &packageReader);
+ if (FAILED(hr)) {
+ qCWarning(lcWinRtRunner).nospace() << "Failed to instantiate package reader. (0x"
+ << QByteArray::number(hr, 16).constData()
+ << ' ' << qt_error_string(hr) << ')';
+ d->hasFatalError = true;
+ return;
}
- d->hasFatalError = true;
- return;
- }
+ hr = packageReader->GetManifest(&d->manifestReader);
+ if (FAILED(hr)) {
+ qCWarning(lcWinRtRunner).nospace() << "Failed to query manifext reader from package";
+ d->hasFatalError = true;
+ return;
+ }
+ } else {
+ if (!getManifestFile(runner->app(), &d->manifest)) {
+ qCWarning(lcWinRtRunner) << "Unable to determine manifest file from" << runner->app();
+ d->hasFatalError = true;
+ return;
+ }
+
+ ComPtr<IStream> manifestStream;
+ hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream);
+ CHECK_RESULT_FATAL("Failed to open manifest stream.", return);
+
+ hr = d->packageFactory->CreateManifestReader(manifestStream.Get(), &d->manifestReader);
+ if (FAILED(hr)) {
+ qCWarning(lcWinRtRunner).nospace() << "Failed to instantiate manifest reader. (0x"
+ << QByteArray::number(hr, 16).constData()
+ << ' ' << qt_error_string(hr) << ')';
+ // ### TODO: read detailed error from event log directly
+ if (hr == APPX_E_INVALID_MANIFEST) {
+ qCWarning(lcWinRtRunner) << "More information on the error can "
+ "be found in the event log under "
+ "Microsoft\\Windows\\AppxPackagingOM";
+ }
+ d->hasFatalError = true;
+ return;
+ }
+ }
ComPtr<IAppxManifestPackageId> packageId;
- hr = manifestReader->GetPackageId(&packageId);
+ hr = d->manifestReader->GetPackageId(&packageId);
CHECK_RESULT_FATAL("Unable to obtain the package ID from the manifest.", return);
APPX_PACKAGE_ARCHITECTURE arch;
@@ -440,7 +467,7 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd)
#endif // _MSC_VER >= 1900
ComPtr<IAppxManifestApplicationsEnumerator> applications;
- hr = manifestReader->GetApplications(&applications);
+ hr = d->manifestReader->GetApplications(&applications);
CHECK_RESULT_FATAL("Failed to get a list of applications from the manifest.", return);
BOOL hasCurrent;
@@ -455,12 +482,12 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd)
LPWSTR executable;
application->GetStringValue(L"Executable", &executable);
CHECK_RESULT_FATAL("Failed to retrieve the application executable from the manifest.", return);
- d->executable = QFileInfo(d->manifest).absoluteDir()
+ d->executable = QFileInfo(runner->app()).absoluteDir()
.absoluteFilePath(QString::fromWCharArray(executable));
CoTaskMemFree(executable);
ComPtr<IAppxManifestPackageDependenciesEnumerator> dependencies;
- hr = manifestReader->GetPackageDependencies(&dependencies);
+ hr = d->manifestReader->GetPackageDependencies(&dependencies);
CHECK_RESULT_FATAL("Failed to retrieve the package dependencies from the manifest.", return);
hr = dependencies->GetHasCurrent(&hasCurrent);
diff --git a/src/winrtrunner/appxengine_p.h b/src/winrtrunner/appxengine_p.h
index 982c484b2..6ff41fed6 100644
--- a/src/winrtrunner/appxengine_p.h
+++ b/src/winrtrunner/appxengine_p.h
@@ -84,6 +84,7 @@ public:
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IUriRuntimeClassFactory> uriFactory;
Microsoft::WRL::ComPtr<IAppxFactory> packageFactory;
+ Microsoft::WRL::ComPtr<IAppxManifestReader> manifestReader;
};
#define wchar(str) reinterpret_cast<LPCWSTR>(str.utf16())
diff --git a/src/winrtrunner/appxphoneengine.cpp b/src/winrtrunner/appxphoneengine.cpp
index a71d03936..fb78e350b 100644
--- a/src/winrtrunner/appxphoneengine.cpp
+++ b/src/winrtrunner/appxphoneengine.cpp
@@ -224,8 +224,14 @@ AppxPhoneEngine::AppxPhoneEngine(Runner *runner)
d->hasFatalError = true;
ComPtr<IStream> manifestStream;
- HRESULT hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream);
- RETURN_VOID_IF_FAILED("Failed to open manifest stream");
+ HRESULT hr;
+ if (d->manifestReader) {
+ hr = d->manifestReader->GetStream(&manifestStream);
+ RETURN_VOID_IF_FAILED("Failed to query manifest stream from manifest reader.");
+ } else {
+ hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream);
+ RETURN_VOID_IF_FAILED("Failed to open manifest stream");
+ }
if (!getPhoneProductId(manifestStream.Get(), &d->productId)) {
qCWarning(lcWinRtRunner) << "Failed to read phone product ID from the manifest.";
@@ -393,23 +399,22 @@ bool AppxPhoneEngine::install(bool removeFirst)
if (!installDependencies())
return false;
- const QDir base = QFileInfo(d->manifest).absoluteDir();
- const QString packageFileName = base.absoluteFilePath(d->packageFamilyName + QStringLiteral(".appx"));
- if (!createPackage(packageFileName))
- return false;
-
- if (!sign(packageFileName))
- return false;
-
- ComPtr<IStream> manifestStream;
- hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream);
- RETURN_FALSE_IF_FAILED("Failed to open manifest stream");
+ const QDir base = QFileInfo(d->executable).absoluteDir();
+ const bool existingPackage = d->runner->app().endsWith(QLatin1String(".appx"));
+ const QString packageFileName = existingPackage
+ ? d->runner->app()
+ : base.absoluteFilePath(d->packageFamilyName + QStringLiteral(".appx"));
+ if (!existingPackage) {
+ if (!createPackage(packageFileName))
+ return false;
- ComPtr<IAppxManifestReader> manifestReader;
- hr = d->packageFactory->CreateManifestReader(manifestStream.Get(), &manifestReader);
- RETURN_FALSE_IF_FAILED("Failed to create manifest reader for installation");
+ if (!sign(packageFileName))
+ return false;
+ } else {
+ qCDebug(lcWinRtRunner) << "Installing existing package.";
+ }
- return installPackage(manifestReader.Get(), packageFileName);
+ return installPackage(d->manifestReader.Get(), packageFileName);
}
bool AppxPhoneEngine::remove()