アプリ パッケージを作成する方法 (C++)
パッケージ化 API を使用して Windows アプリのアプリ パッケージを作成する方法について説明します。
デスクトップ アプリ パッケージを手動で作成する場合は、パッケージ化 API を利用する MakeAppx.exe ツールを使用することもできます。 詳細については、 アプリ パッケージャー (MakeAppx.exe) を参照してください。
Visual Studio を使用している場合は、Visual Studio パッケージ化ウィザードを使用してアプリをパッケージ化することをお勧めします。 詳細については、「Visual Studio を使用して UWP アプリをパッケージ化する」を参照してください。
手順
手順 1: パッケージ ライターを作成する
パッケージ ライターを作成するには、IAppxFactory::CreatePackageWriter メソッドを呼び出します。 最初のパラメーターは、パッケージが書き込まれる出力ストリームです。 2 番目のパラメーターは、パッケージ設定を指定する APPX_PACKAGE_SETTINGS 構造体へのポインターです。 3 番目のパラメーターは、IAppxPackageWriter ポインターへのポインターを受け取る出力パラメーターです。
#include <windows.h>
#include <shlwapi.h>
#include <AppxPackaging.h>
// We store the produced package under this file name.
const LPCWSTR OutputPackagePath = L"HelloWorld.appx";
int wmain()
{
HRESULT hr = S_OK;
// Specify the appropriate COM threading model
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(hr))
{
// Create a package writer
IAppxPackageWriter* packageWriter = NULL;
hr = GetPackageWriter(OutputPackagePath, &packageWriter);
}
}
//
// Creates an app package writer with default settings.
//
// Parameters:
// outputFileName
// Fully qualified name of the app package (.appx file) to be created.
// writer
// On success, receives the created instance of IAppxPackageWriter.
//
HRESULT GetPackageWriter(
_In_ LPCWSTR outputFileName,
_Outptr_ IAppxPackageWriter** writer)
{
const LPCWSTR Sha256AlgorithmUri = L"https://www.w3.org/2001/04/xmlenc#sha256";
HRESULT hr = S_OK;
IStream* outputStream = NULL;
IUri* hashMethod = NULL;
APPX_PACKAGE_SETTINGS packageSettings = {0};
IAppxFactory* appxFactory = NULL;
// Create a stream over the output file for the package
hr = SHCreateStreamOnFileEx(
outputFileName,
STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE,
0, // default file attributes
TRUE, // create file if it does not exist
NULL, // no template
&outputStream);
// Create default package writer settings, including hash algorithm URI
// and Zip format.
if (SUCCEEDED(hr))
{ hr = CreateUri(
Sha256AlgorithmUri,
Uri_CREATE_CANONICALIZE,
0, // reserved parameter
&hashMethod);
}
if (SUCCEEDED(hr))
{
packageSettings.forceZip32 = TRUE;
packageSettings.hashMethod = hashMethod;
}
// Create a new Appx factory
if (SUCCEEDED(hr))
{
hr = CoCreateInstance(
__uuidof(AppxFactory),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IAppxFactory),
(LPVOID*)(&appxFactory));
}
// Create a new package writer using the factory
if (SUCCEEDED(hr))
{
hr = appxFactory->CreatePackageWriter(
outputStream,
&packageSettings,
writer);
}
// Clean up allocated resources
if (appxFactory != NULL)
{
appxFactory->Release();
appxFactory = NULL;
}
if (hashMethod != NULL)
{
hashMethod->Release();
hashMethod = NULL;
}
if (outputStream != NULL)
{
outputStream->Release();
outputStream = NULL;
}
return hr;
}
手順 2: アプリのペイロード ファイルをパッケージに追加する
IAppxPackageWriter::AddPayloadFile メソッドを呼び出して、パッケージにファイルを追加します。 最初のパラメータは、ファイルの相対パスです。 2 番目のパラメーターは、ファイルのコンテンツ タイプを示します。 3 番目のパラメーターは、APPX_COMPRESSION_OPTION リストのオプションを指定します。 4 番目のパラメーターは、ファイルの入力ストリームです。
// Path where all input files are stored
const LPCWSTR DataPath = L"Data\\";
// Add all payload files to the package writer
for (int i = 0; SUCCEEDED(hr) && (i < PayloadFilesCount); i++)
{
IStream* fileStream = NULL;
hr = GetFileStream(DataPath, PayloadFilesName[i], &fileStream);
if (SUCCEEDED(hr))
{
packageWriter->AddPayloadFile(
PayloadFilesName[i],
PayloadFilesContentType[i],
PayloadFilesCompression[i],
fileStream);
}
if (fileStream != NULL)
{
fileStream->Release();
fileStream = NULL;
}
}
}
前のコードでは、これらの変数定義と GetFileStream
ヘルパー関数を使用します。
#include <strsafe.h>
#include <shlwapi.h>
// The produced app package's content consists of these files, with
// corresponding content types and compression options.
const int PayloadFilesCount = 4;
const LPCWSTR PayloadFilesName[PayloadFilesCount] = {
L"AppTile.png",
L"Default.html",
L"images\\smiley.jpg",
L"Error.html",
};
const LPCWSTR PayloadFilesContentType[PayloadFilesCount] = {
L"image/png",
L"text/html",
L"image/jpeg",
L"text/html",
};
const APPX_COMPRESSION_OPTION PayloadFilesCompression[PayloadFilesCount] = {
APPX_COMPRESSION_OPTION_NONE,
APPX_COMPRESSION_OPTION_NORMAL,
APPX_COMPRESSION_OPTION_NONE,
APPX_COMPRESSION_OPTION_NORMAL,
};
//
// Creates a readable IStream over the specified file. For simplicity, we assume that the fully
// qualified file name is 100 characters or less. Your code should
// handle longer names, and allocate the buffer dynamically.
//
// Parameters:
// path
// Path of the folder that contains the file to be opened; must end with a '\'
// fileName
// Name, of the file to be opened, not including the path
// stream
// On success, receives the created instance of IStream
//
HRESULT GetFileStream(
_In_ LPCWSTR path,
_In_ LPCWSTR fileName,
_Outptr_ IStream** stream)
{
HRESULT hr = S_OK;
const int MaxFileNameLength = 100;
WCHAR fullFileName[MaxFileNameLength + 1];
// Create full file name by concatenating path and fileName
hr = StringCchCopyW(fullFileName, MaxFileNameLength, path);
if (SUCCEEDED(hr))
{
hr = StringCchCat(fullFileName, MaxFileNameLength, fileName);
}
// Create stream for reading the file
if (SUCCEEDED(hr))
{
hr = SHCreateStreamOnFileEx(
fullFileName,
STGM_READ | STGM_SHARE_EXCLUSIVE,
0, // default file attributes
FALSE, // don't create new file
NULL, // no template
stream);
}
return hr;
}
手順 3: パッケージ マニフェストをパッケージに追加する
すべてのパッケージにはパッケージ マニフェストが必要です。 パッケージ マニフェストをパッケージに追加するには、ファイルの入力ストリームを作成し、IAppxPackageWriter::Close メソッドを呼び出してパッケージの末尾にマニフェストを書き込み、パッケージ ライターの出力ストリームを閉じます。
このコードでは、前の手順で示した GetFileStream
ヘルパー関数を使用して、パッケージ マニフェストのストリームを作成します。
// We read the app package's manifest from this file
const LPCWSTR ManifestFileName = L"AppxManifest.xml";
IStream* manifestStream = NULL;
hr = GetFileStream(DataPath, ManifestFileName, &manifestStream);
if (SUCCEEDED(hr))
{
hr = packageWriter->Close(manifestStream);
}
if (manifestStream != NULL)
{
manifestStream->Release();
manifestStream = NULL;
}
手順 4: パッケージ ライターをクリーンアップする
wmain
関数から戻る前に、Release メソッドを呼び出してパッケージ ライターをクリーンアップし、CoUninitialize 関数を呼び出します。
if (packageWriter != NULL)
{
packageWriter->Release();
packageWriter = NULL;
}
CoUninitialize();
関連トピック
-
サンプル
-
リファレンス