Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Learn how to get info from the app package manifest for a Windows app using the packaging API.
Create a package manifest reader
To create a package manifest reader, call IAppxFactory::CreatePackageReader to create a package reader. The first parameter is an input stream for the package (.appx file). The second parameter is an output parameter that receives a pointer to an IAppxPackageReader pointer. Next, call IAppxPackageReader::GetManifest to get the manifest reader. The parameter is an output parameter that receives a pointer to an IAppxManifestReader pointer.
int wmain(
_In_ int argc,
_In_reads_(argc) wchar_t** argv)
{
HRESULT hr = S_OK;
if (argc != 2)
{
wprintf(L"Usage: DescribeAppx.exe inputFile\n");
wprintf(L" inputFile: Path to the app package to read\n");
return 2;
}
// Specify the appropriate COM threading model
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(hr))
{
IAppxPackageReader* packageReader = NULL;
IAppxManifestReader* manifestReader = NULL;
// Create a package reader using the file name given in command line
hr = GetPackageReader(argv[1], &packageReader);
// Get manifest reader for the package and read from the manifest
if (SUCCEEDED(hr))
{
hr = packageReader->GetManifest(&manifestReader);
}
if (SUCCEEDED(hr))
{
hr = ReadManifest(manifestReader);
}
}
}
//
// Creates an app package reader.
//
// Parameters:
// inputFileName
// Fully qualified name of the app package (.appx file) to be opened.
// reader
// On success, receives the created instance of IAppxPackageReader.
//
HRESULT GetPackageReader(
_In_ LPCWSTR inputFileName,
_Outptr_ IAppxPackageReader** reader)
{
HRESULT hr = S_OK;
IAppxFactory* appxFactory = NULL;
IStream* inputStream = NULL;
// Create a new factory
hr = CoCreateInstance(
__uuidof(AppxFactory),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IAppxFactory),
(LPVOID*)(&appxFactory));
// Create a stream over the input app package
if (SUCCEEDED(hr))
{
hr = SHCreateStreamOnFileEx(
inputFileName,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0, // default file attributes
FALSE, // do not create new file
NULL, // no template
&inputStream);
}
// Create a new package reader using the factory. For
// simplicity, we don't verify the digital signature of the package.
if (SUCCEEDED(hr))
{
hr = appxFactory->CreatePackageReader(
inputStream,
reader);
}
// Clean up allocated resources
if (inputStream != NULL)
{
inputStream->Release();
inputStream = NULL;
}
if (appxFactory != NULL)
{
appxFactory->Release();
appxFactory = NULL;
}
return hr;
}
Read package identity info
Package identify is specified using the Identity element in the manifest. Use IAppxManifestReader::GetPackageId to get an IAppxManifestPackageId to read package identity info, as shown here.
This code uses IAppxManifestPackageId::GetPackageFullName to get the package full name, IAppxManifestPackageId::GetName to get the package name, and IAppxManifestPackageId::GetVersion to get the package version.
//
// Reads a subset of the manifest Identity element.
//
//
HRESULT ReadManifestPackageId(
_In_ IAppxManifestReader* manifestReader)
{
HRESULT hr = S_OK;
IAppxManifestPackageId* packageId = NULL;
// Get elements and attributes from the manifest reader
hr = manifestReader->GetPackageId(&packageId);
if (SUCCEEDED(hr))
{
LPWSTR packageFullName = NULL;
LPWSTR packageName = NULL;
UINT64 packageVersion = 0;
hr = packageId->GetPackageFullName(&packageFullName);
if (SUCCEEDED(hr))
{
hr = packageId->GetName(&packageName);
}
if (SUCCEEDED(hr))
{
hr = packageId->GetVersion(&packageVersion);
}
if (SUCCEEDED(hr))
{
wprintf(L"Package full name: %s\n", packageFullName);
wprintf(L"Package name: %s\n", packageName);
wprintf(L"Package version: ");
// Convert version number from 64-bit integer to dot-quad form
for (int bitPosition = 0x30; bitPosition >= 0; bitPosition -= 0x10)
{
UINT64 versionWord = (packageVersion >> bitPosition) & 0xFFFF;
wprintf(L"%llu.", versionWord);
}
wprintf(L"\n");
}
// Free all string buffers returned from the manifest API
CoTaskMemFree(packageFullName);
CoTaskMemFree(packageName);
}
// Clean up allocated resources
if (packageId != NULL)
{
packageId->Release();
packageId = NULL;
}
return hr;
}
Read metadata that describes the package to users
Properties are specified using the Properties element in the manifest. Use IAppxManifestReader::GetProperties to get an IAppxManifestProperties to read this node, as shown here.
This code uses IAppxManifestProperties::GetStringValue to get the package display name and package description.
//
// Reads a subset of the manifest Properties element.
//
//
HRESULT ReadManifestProperties(
_In_ IAppxManifestReader* manifestReader)
{
HRESULT hr = S_OK;
IAppxManifestProperties* properties = NULL;
// Get elements and attributes from the manifest reader
hr = manifestReader->GetProperties(&properties);
if (SUCCEEDED(hr))
{
LPWSTR displayName = NULL;
LPWSTR description = NULL;
hr = properties->GetStringValue(L"DisplayName", &displayName);
if (SUCCEEDED(hr))
{
hr = properties->GetStringValue(L"Description", &description);
}
if (SUCCEEDED(hr))
{
wprintf(L"Package display name: %s\n", displayName);
wprintf(L"Package description: %s\n", description);
}
// Free all string buffers returned from the manifest API
CoTaskMemFree(displayName);
CoTaskMemFree(description);
}
// Clean up allocated resources
if (properties != NULL)
{
properties->Release();
properties = NULL;
}
return hr;
}
Read metadata about the apps included in the package
Apps are specified using the Applications element in the manifest. Use IAppxManifestReader::GetApplications to get an IAppxManifestApplicationsEnumerator to read this node. Use IAppxManifestApplicationsEnumerator::GetCurrent and IAppxManifestApplicationsEnumerator::MoveNext to get an IAppxManifestApplication for each app in the package.
This code uses IAppxManifestApplication::GetStringValue to get the display name for each app.
//
// Reads a subset of the manifest Applications element.
//
//
HRESULT ReadManifestApplications(
_In_ IAppxManifestReader* manifestReader)
{
HRESULT hr = S_OK;
BOOL hasCurrent = FALSE;
UINT32 applicationsCount = 0;
IAppxManifestApplicationsEnumerator* applications = NULL;
// Get elements and attributes from the manifest reader
hr = manifestReader->GetApplications(&applications);
if (SUCCEEDED(hr))
{
hr = applications->GetHasCurrent(&hasCurrent);
while (SUCCEEDED(hr) && hasCurrent)
{
IAppxManifestApplication* application = NULL;
LPWSTR applicationName = NULL;
hr = applications->GetCurrent(&application);
if (SUCCEEDED(hr))
{
application->GetStringValue(L"DisplayName", &applicationName);
}
if (SUCCEEDED(hr))
{
applicationsCount++;
wprintf(L"App #%u: %s\n", applicationsCount, applicationName);
}
if (SUCCEEDED(hr))
{
hr = applications->MoveNext(&hasCurrent);
}
if (application != NULL)
{
application->Release();
application = NULL;
}
CoTaskMemFree(applicationName);
}
wprintf(L"Count of apps in the package: %u\n", applicationsCount);
}
// Clean up allocated resources
if (applications != NULL)
{
applications->Release();
applications = NULL;
}
return hr;
}
Clean up the package manifest reader
Before returning from the wmain
function, call the Release method to clean up the package manifest reader and call the CoUninitialize function.
// Clean up allocated resources
if (manifestReader != NULL)
{
manifestReader->Release();
manifestReader = NULL;
}
if (packageReader != NULL)
{
packageReader->Release();
packageReader = NULL;
}
CoUninitialize();
Related topics
-
Samples
-
Reference