备注

如果您要创建UWP应用程序包,请参阅使用MakeAppx.exe工具创建应用程序包。

了解如何使用打包API为Windows应用商店应用创建应用包。

如果要手动创建桌面应用程序包,还可以使用使用打包API的MakeAppx.exe工具。有关详细信息,请参阅App packager(MakeAppx.exe)。

如果您使用的是Visual Studio,建议您使用Visual Studio打包向导打包您的应用程序。有关更多详细信息,请参阅打包UWP应用程序。

说明

第1步:创建包编写器

要创建包编写器,请调用IAppxFactory :: CreatePackageWriter方法。第一个参数是将写入包的输出流。第二个参数是指向APPX_PACKAGE_SETTINGS结构的指针,该结构指定包设置。第三个参数是一个输出参数,它接收指向IAppxPackageWriter指针的指针。

C ++复制
#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气动卸灰球阀(喷煤粉专用球阀)

C ++复制
// 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辅助函数。

C ++复制
#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上一步中显示的帮助程序函数为程序包清单创建流。

C ++复制
// 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函数。

C ++复制
if (packageWriter != NULL)
{
    packageWriter->Release();
    packageWriter = NULL;
}
CoUninitialize();

如何创建应用程序包(C ++)的更多相关文章

  1. Win10 创建应用程序包及部署

    https://msdn.microsoft.com/zh-cn/library/windows/apps/xaml/hh454036.aspx https://msdn.microsoft.com/ ...

  2. 如何以编程方式签署应用程序包(C ++)

    了解如何使用SignerSignEx2函数对应用包进行签名. 如果要使用Packaging API以编程方式创建Windows应用商店应用包,则还需要在部署之前对应用包进行签名.Packaging A ...

  3. 如何使用SignTool签署应用程序包

    备注 有关签署UWP应用程序包的信息,请参阅使用SignTool签署应用程序包. 了解如何使用SignTool对Windows应用商店应用包进行签名,以便部署它们.SignTool是Windows软件 ...

  4. Silverlight 之 创建

          Silverlight 项目文件是您可以使用不同工具来创建和编辑的文本文件.例如,可以使用 Visual Studio 2010 以及 Expression Blend 来创建 Silve ...

  5. UWP 从创建到发布流程一栏

    # UWP的产品新建到发布流程一览 1,UWP开发特性 U: Universal(通用) W: Windows P: Plantform(平台) 运行在Windows10设备 比WPF更加多样化和完善 ...

  6. xamarin.forms uwp app部署到手机移动设备进行测试,真机调试(device portal方式部署)

    最近学习xamarin.刚好 手上有一个lumia 930.所以试一试把uwp app部署到手机上,并真机调试一把. 目前环境: 1.开发pc电脑是win10,版本1607.加入了insider,所以 ...

  7. 我的第一个WP8.1应用总结

    我的LUMIA925已经买了很久了,想自己开发WP应用放在上面,却一直想不到有什么特别的想法和需要.前几天的事情正好让我有了这个机会. 前几天在客户机房工作的时候,同事打电话来说另一个客户由于换了电脑 ...

  8. iOS开发-- 开发环境,证书和授权文件

    一.成员介绍 1.    Certification(证书)证书是对电脑开发资格的认证,每个开发者帐号有一套,分为两种:1)    Developer Certification(开发证书)安装在电脑 ...

  9. IOS 开发环境,证书和授权文件等详解

    (转自:http://blog.csdn.net/gtncwy/article/details/8617788) 一.成员介绍1.    Certification(证书)证书是对电脑开发资格的认证, ...

随机推荐

  1. 15.app后端怎么设计用户登录方案

    在很多app中,都需要用户的登录操作.登录,就需要用到用户名和密码.为了安全起见,暴露明文密码的次数越少越好.怎么能最大程度避免泄露用户的密码呢?在登录后,app后端怎么去验证和维持用户的登录状态呢? ...

  2. app后端设计(13)--IM4JAVA+GraphicsMagick实现中文水印

    在app的后台中,有时候为了标示版权,需要给图片加上水印. 在liunx中,IM4JAVA+GraphicsMagick是个高效处理图片的方案,图片的裁剪是使用了这个技术方案,为了减少不必要的开发成本 ...

  3. Mac下显示隐藏的文件

    显示隐藏文件defaults write com.apple.finder AppleShowAllFiles -bool true; KillAll Finder恢复隐藏文件 defaults wr ...

  4. BZOJ_1266_[AHOI2006]上学路线route_最小割

    BZOJ_1266_[AHOI2006]上学路线route_最小割 Description 可可和卡卡家住合肥市的东郊,每天上学他们都要转车多次才能到达市区西端的学校.直到有一天他们两人参加了学校的信 ...

  5. BZOJ_2242_[SDOI2011]计算器_快速幂+扩展GCD+BSGS

    BZOJ_2242_[SDOI2011]计算器_快速幂+扩展GCD+BSGS 题意: 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p, ...

  6. 【爆料】-《昆士兰大学毕业证书》Queensland一模一样原件

    ☞昆士兰大学毕业证书[微/Q:2544033233◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归& ...

  7. python+appium 【已解决】真机运行appium报错“WebDriverException: Message: A new session could not be created. (Original error: Command failed: C:\Windows\system32\cmd.exe /s /c.......详见内文

    问题报错提示: selenium.common.exceptions.WebDriverException: Message: A new session could not be created. ...

  8. C++的代理类

    怎样在一个容器中包含类型不同,但是彼此有关系的对象?众所周知,C++的容器只能存放类型相同的元素,所以直接在一个容器中存储不同类型的对象本身是不可能的,只能通过以下两种方案实现: 1. 提供一个间接层 ...

  9. TiDB show processlist命令源码分析

    背景 因为丰巢自去年年底开始在推送平台上尝试了TiDB,最近又要将承接丰巢所有交易的支付平台切到TiDB上.我本人一直没有抽出时间对TiDB的源码进行学习,最近准备开始一系列的学习和分享.由于我本人没 ...

  10. 分布式系统关注点(15)——「水平&垂直切分」详解

    如果第二次看到我的文章,欢迎右侧扫码订阅我哟~