如何创建应用程序包(C ++)
备注
如果您要创建uwp应用程序包,请参阅使用makeappx.exe工具创建应用程序包。
了解如何使用打包api为windows应用商店应用创建应用包。
如果要手动创建桌面应用程序包,还可以使用使用打包api的makeappx.exe工具。有关详细信息,请参阅app packager(makeappx.exe)。
如果您使用的是visual studio,建议您使用visual studio打包向导打包您的应用程序。有关更多详细信息,请参阅打包uwp应用程序。
说明
第1步:创建包编写器
要创建包编写器,请调用iappxfactory :: createpackagewriter方法。第一个参数是将写入包的输出流。第二个参数是指向appx_package_settings结构的指针,该结构指定包设置。第三个参数是一个输出参数,它接收指向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方法将文件添加到包中。第一个参数是文件的相对路径。第二个参数表示文件的内容类型。第三个参数指定appx_compression_option枚举中的选项。第四个参数是文件的输入流。以下效果展示
黄铜浮球阀, 不锈钢法兰浮球阀, 不锈钢水箱浮球阀, q941f-16p不锈钢电动球阀, 丝扣浮球阀, 黄铜小孔浮球阀, z45x暗杆软密封闸阀, gly储油罐量油孔, fzt防爆阻火呼吸人孔, cwx微型电动球阀, q941f电动开关球阀, q941f电动法兰球阀, q911f电动内螺纹球阀, q671f气动对夹式球阀, q611n气动高压球阀, q641f气动带手动球阀, q611f气动三片式球阀, q611f气动两片式球阀, q641f气动调节球阀, q971f电动对夹球阀, q641f不锈钢气动球阀, 不锈钢高压球阀, 超高压球阀, q41y高压硬密封球阀, qj41m耐高温球阀, qj41m不锈钢高温球阀, 法兰高温球阀, q41h高温硬密封球阀, q41h金属硬密封高温球阀, (q45f)t型三通球阀, (q44f)l型三通球阀, khb3k高压三通球阀, bq71f薄型保温球阀, q11f螺纹球阀, q11f内螺纹球阀, q21f外螺纹球阀, q41f法兰球阀, q41f法兰式球阀, q61f焊接球阀, q61f全焊接球阀, q61f焊接式球阀, q71f对夹球阀, q71f对夹式球阀, q61n对焊球阀, q91f卡套球阀, q91f不锈钢卡套球阀, q41n锻钢球阀, q61n焊接锻钢球阀, q41n高压锻钢球阀, kq41f不锈钢抗硫球阀, 切断球阀, 气动切断球阀-气动o型切断球阀, 电动切断球阀-电动o型切断球阀, q46f不锈钢四通球阀, q46f四通球阀, q41f燃气球阀, q41f燃气专用球阀, q81f卫生球阀, q81f快装球阀, q81f卫生级快装球阀, q81f卫生级球阀, q681f卫生级气动球阀, 广式球阀, q11f广式内螺纹球阀, q21f广式外螺纹球阀, q41f广式法兰球阀, q11f丝口球阀, q11f丝扣球阀, v型球阀, 电动v型球阀, 气动v型球阀, yjzq高压液压球阀, khbf-khmf法兰式高压球阀, cjzq高压球阀, vh3v二位三通高压球阀, bkh-mkh高压球阀, vh2v直通高压球阀, bme高压球阀, khb高压球阀, khp-pkh高压板式球阀, (喷煤粉)卸灰球阀, q647mf气动卸灰球阀(喷煤粉专用球阀)
// 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();
上一篇: 第六节--访问属性和方法