---
title: 发布到微软商店
tags: [发布, MSIX, 微软商店]
---

# 把自己写的软件上架微软商店，是一种怎样的体验

本文记录了把 Tydora（一款基于 Tauri v2 的桌面 Markdown 编辑器）发布到微软商店（Microsoft Store）的完整过程，包含 MSIX 打包、Partner Center 配置、GitHub Actions 自动发布的全流程，以及途中踩过的所有坑。

> 适用于：Tauri v2 桌面应用、希望上架微软商店的个人/小团队开发者。  
> 本文最后更新：2026 年 8 月 8 日。

## 背景：为什么是 MSIX

Tydora 的默认分发方式是 NSIS（`.exe`）+ MSI（`.msi`）+ macOS/Linux 包，通过 GitHub Releases 发布。但微软商店**只接受 MSIX 格式**，且 Tauri CLI 2.11.2 在 Windows 平台的 `--bundles` 不支持 `msix` 目标（只有 `msi`/`nsis`）。

所以我们的思路是：

1. 用 `tauri build --no-bundle` 产出**原始 release exe**（前端已内嵌到二进制）
2. 自己写一份 ` AppxManifest.xml`
3. 用 Windows SDK 的 `MakeAppx.exe` 把 `exe` + 清单 + 图标打包成 `.msix`
4. 上传到 `Partner Center`，由微软统一签名后上架

整个过程不依赖 `Tauri `的 `MSIX bundler`，可控且能精确对齐商店身份。

## 全流程概览

```
┌──────────────────────────────────┐
│ 1. Partner Center 注册账号       │
│    + 保留产品名 + 拿商店身份      │
└────────────┬─────────────────────┘
             │
             ▼
┌──────────────────────────────────┐
│ 2. 配置 .env 里的 MSSTORE_*      │
│    Name / Publisher / DisplayName │
└────────────┬─────────────────────┘
             │
             ▼
┌──────────────────────────────────┐
│ 3. npm run tauri build:msix      │
│    生成未签名 MSIX（商店模式）    │
└────────────┬─────────────────────┘
             │
             ▼
┌──────────────────────────────────┐
│ 4. 上传到 Partner Center          │
│    填隐私策略 / 支持信息 / 渠道   │
│    首个版本必须手动上传           │
└────────────┬─────────────────────┘
             │
             ▼
┌──────────────────────────────────┐
│ 5. 等待微软认证（1-3 工作日）     │
│    通过 → 上架                    │
└────────────┬─────────────────────┘
             │
             ▼
┌──────────────────────────────────┐
│ 6. 配置 GitHub Actions Secrets    │
│    后续版本走 CI 自动发布          │
└──────────────────────────────────┘
```

## 第 1 步：Partner Center 注册与保留产品名

### 1.1 注册开发者账号

打开 [storedeveloper.microsoft.com](https://storedeveloper.microsoft.com/) 用微软账号登录，选「个人开发者」（个人号几分钟过审，免费；公司号需 DUNS 或营业执照，2-5 工作日）。

### 1.2 新建产品并保留名称

进入 [Partner Center](https://partner.microsoft.com/) → **Apps and games** → **New product**。

> [!WARNING]产品类型必须选「MSIX 或 PWA 应用」（MSIX or PWA app）。如果选了「EXE 或 MSI app」，上传 MSIX 时会被直接拒绝，且产品类型创建后无法更改，只能删掉重建。

输入产品名「**Tydora**」并保留（名字保留后 3 个月内必须发布，否则失效）。

### 1.3 拿到商店身份

保留成功后进入应用页面 → 顶部 **Product identity**（产品标识）页：

| 字段 | 示例值 | 用途 |
| --- | --- | --- |
| Package/Identity/Name | `<你的Name>`（形如 `1234567890.Tydora`） | MSIX 清单的 `Identity Name` |
| Package/Identity/Publisher | `<你的Publisher>`（形如 `CN=XXXX-XXXX-...`） | MSIX 清单的 `Identity Publisher` |
| PublisherDisplayName | `<你的发布者显示名>` | MSIX 清单的 `Properties/PublisherDisplayName` |
| Store product ID | `<你的ProductID>`（形如 `9WZDNCRFXXXX`） | 后续 CI 自动发布用 |

**这三个值（Name / Publisher / PublisherDisplayName）必须和你 MSIX 清单里的值一字不差**，否则 Partner Center 校验会打回。下面会讲怎么把这三个值注入清单。

## 第 2 步：MSIX 清单与打包脚本

### 2.1 AppxManifest.xml 模板

`Tauri `不生成 `MSIX `清单，我们自己写一份，放在 `src-tauri/msix/AppxManifest.xml`。关键点：

```xml
<Identity Name="{{PACKAGE_IDENTITY_NAME}}"
          Publisher="{{PUBLISHER}}"
          Version="{{VERSION}}"
          ProcessorArchitecture="x64" />

<Properties>
  <DisplayName>Tydora</DisplayName>
  <PublisherDisplayName>{{PUBLISHER_DISPLAY_NAME}}</PublisherDisplayName>
  <Logo>Assets\StoreLogo.png</Logo>
  <Description>A modern Markdown editor built with Tauri</Description>
</Properties>
```

三个 `{{...}}` 占位符由打包脚本在运行时替换为实际值。

> [!WARNING]<Properties> 下的子元素顺序有 XML Schema 严格约束：必须是 DisplayName → PublisherDisplayName → Logo → Description。如果 Description 写在 Logo 前面，MakeAppx 会报 C00CEE3B（app manifest XML must be valid），但错误信息是乱码是（????????????????），很难定位。
> 这是本文踩过的第一个大坑——错误位置在 Line 28, Column 15，但真正的问题在 line 25 的元素顺序。

### 2.2 文件关联（可选）

如果想让应用接管 `.md` 文件，在 `<Applications>` 节点加 `<Extensions>`：

```xml
<Extensions>
  <uap:Extension Category="windows.fileTypeAssociation">
    <uap:FileTypeAssociation Name="markdown">
      <uap:SupportedFileTypes>
        <uap:FileType>.md</uap:FileType>
        <uap:FileType>.markdown</uap:FileType>
        <uap:FileType>.mdx</uap:FileType>
      </uap:SupportedFileTypes>
    </uap:FileTypeAssociation>
  </uap:Extension>
</Extensions>
```

### 2.3 能力声明（Capabilities）

```xml
<Capabilities>
  <rescap:Capability Name="runFullTrust" />  <!-- 桌面应用必须 -->
  <Capability Name="internetClient" />        <!-- 自动更新检查 -->
</Capabilities>
```

`runFullTrust` 是**受限能力**，提交时 Partner Center 会强制要求你解释用途（见第 4.3 节）。

### 2.4 打包脚本 build-msix.ps1

核心流程：

1. **判定模式**：检查 `MSSTORE_PACKAGE_IDENTITY_NAME` 和 `MSSTORE_PUBLISHER` 是否同时存在
   - 都存在 → **商店模式**（不签名，产物给 Partner Center）
   - 任一缺失 → **本地测试模式**（自签名，本地可安装）
2. **读取 release exe**：`src-tauri/target/release/tydora.exe`
3. **暂存目录**：`src-tauri/target/msix-staging/`，把 exe + 图标 + 生成的 manifest 放进去
4. **MakeAppx pack**：打包成 `src-tauri/target/msix/Tydora_<version>_x64.msix`
5. **签名**（仅本地模式或显式 `-Sign`）：用 `Sign-AppxPackage` 创建自签名证书并签名

**版本号来源**：从 `VERSION` 文件读取，转换为四段式 `0.1.4.0`（MSIX 要求 `Major.Minor.Build.Revision` 四段，空位补 0）。

### 2.5 接入 npm 脚本

`scripts/run-tauri.mjs`拦截 `build:msix` 子命令，转发给 `PowerShell `脚本：

```javascript
if (subCommand === 'build:msix') {
    const args = process.argv.slice(3).join(' ');
    spawnSync('pwsh', ['-File', 'scripts/build-msix.ps1', ...args], { stdio: 'inherit' });
}
```

在 `package.json `里注册：

```json
"scripts": {
    "tauri": "node scripts/run-tauri.mjs"
}
```

这样就能用 `npm run tauri build:msix` 打包了。

## 第 3 步：本地打包

### 3.1 配置 .env

在项目根目录的 `.env` 里填入商店身份：

```dotenv
# 已有的 Tauri 签名密钥（用于 NSIS/MSI 自动更新签名，不是 MSIX 签名）
TAURI_SIGNING_PRIVATE_KEY=...
TAURI_SIGNING_PRIVATE_KEY_PASSWORD=...

# 微软商店身份（用于 MSIX 打包）
MSSTORE_PACKAGE_IDENTITY_NAME=<你的Name>
MSSTORE_PUBLISHER=<你的Publisher>
MSSTORE_PUBLISHER_DISPLAY_NAME=<你的发布者显示名>
```

> [!WARNING].env 里的值不要加引号。Tydora 的 loadEnv 解析器只按第一个 = 分割并 trim 两边，不会剥引号。如果写成 MSSTORE_PACKAGE_IDENTITY_NAME="你的Name"，引号会被当作值的一部分传给 MakeAppx，导致 Partner Center 校验 Identity Name 时报错。
> 这是本文踩过的第二个坑——无效的软件包标识名称: Tydora (应为: 你的Name)，实际上是因为之前 .env 里写成了 = " 你的Name"（带前导空格和引号）。

### 3.2 执行打包

```powershell
# 完整打包（含 Rust 编译，首次约 5-10 分钟）
npm run tauri build:msix

# 跳过编译，仅重新打包（已有 release exe 时，秒级）
npm run tauri build:msix -- -SkipBuild

# 跳过签名（商店模式默认就是不签名，加这个只是不显示签名警告）
npm run tauri build:msix -- -SkipBuild -NoSign
```

### 3.3 验证产物

打包成功后，控制台会输出：

```
Identity Name:        <你的Name>
Publisher:            <你的Publisher>
PublisherDisplayName: <你的发布者显示名>
Mode:                 Store (unsigned)
Package creation succeeded.

✓ MSIX 已生成: D:\code\Tydora\src-tauri\target\msix\Tydora_0.1.4.0_x64.msix
  大小: 6.09 MB
```

> [!IMPORTANT]本地双击这个未签名 MSIX 会显示「发布者: 未知」并报错 0x800B010A（证书不受信任），这是正常的——商店模式的包本来就不该本地安装，它只应该上传到 Partner Center，由微软用微软自己的证书统一签名后分发给最终用户。
> 如果你想本地测试安装效果，可以用本地模式（注释掉 .env 里的 MSSTORE\_\* 三行）打一个自签名的包，本地安装不会报错。

## 第 4 步：上传到 Partner Center

### 4.1 开始新提交

进入 Tydora 应用页面 → **Start a submission**（开始新提交）。需要填的几个块：

| 块 | 内容 |
| --- | --- |
| Packages | 上传 `.msix` 文件 |
| Pricing and availability | 免费 / 付费区域 |
| Properties | 应用分类、隐私策略 URL 等 |
| Age ratings | 年龄分级问卷 |
| Store listing | 商店页面文案、截图、图标 |

### 4.2 上传 Packages

在 **Packages** 块，把本地生成的 `Tydora_0.1.4.0_x64.msix` 拖进去。

上传完成后，Partner Center 会自动解析 Identity 信息并校验：

```
Package identifier:  <你的Name>_0.1.4.0_x64__<PFN后缀>
Version:             0.1.4.0
Architecture:        x64
```

如果和你在 Partner Center 注册的 Name/Publisher 一致，就显示绿色 ✓；否则会报类似：

```
无效的软件包标识名称: Tydora (应为: <你的Name>)
无效的软件包发布者名称: CN=Tydora (应为: <你的Publisher>)
```

这时候你需要：

1. 检查 `.env` 里的 `MSSTORE_PACKAGE_IDENTITY_NAME` / `MSSTORE_PUBLISHER` 是否正确
2. 用 `-SkipBuild` 重新打包（秒级）
3. 在 Packages 页**先删除旧包**，再上传新包

### 4.3 填写受限功能说明（runFullTrust）

因为 MSIX 清单里声明了 `rescap:Capability Name="runFullTrust"`，Partner Center 会要求你在「Properties」或「Notes for certification」里解释用途。

**这是我填写的内容**：

> Tydora 是一款桌面 Markdown 编辑器，采用 Tauri v2 框架构建，核心工作模式为「本地优先」——所有笔记、文件、配置都保存在用户自己的设备上，不经过任何云端服务器。
>
> `runFullTrust` 是 Tauri 桌面应用的标准要求，具体用于：
>
> 1. **文件系统读写**：用户通过「仓库」机制选择本地文件夹作为笔记存储位置，应用需要直接读取和写入该文件夹下的 `.md` 文件、图片附件等。
> 2. **文件系统监听**：当用户使用其他编辑器同时编辑笔记时，应用需要监听本地文件变更（通过 Rust `notify` crate），以实时同步链接索引。
> 3. **系统文件对话框**：使用 Tauri `plugin-dialog` 提供原生打开/保存对话框。
> 4. **调用外部程序**：用系统默认应用打开文件、在文件管理器中定位文件等。
> 5. **发布网站功能**：调用本地 Node.js CLI 将 Markdown 构建为静态网站。
>
> 应用**不收集任何用户个人数据**，所有操作均在本地完成；不包含任何第三方分析 SDK 或广告 SDK。`runFullTrust` 仅用于上述桌面应用场景，不会绕过系统安全机制。

### 4.4 隐私策略 URL

微软商店**强制要求**所有应用提供隐私策略 URL。我在文档站专门加了一个页面：[隐私策略 · Tydora](https://zuorn.github.io/Tydora/01-%E5%BC%80%E5%A7%8B%E4%BD%BF%E7%94%A8/%E9%9A%90%E7%A7%81%E7%AD%96%E7%95%A5)

隐私策略内容要点（按微软商店审查清单）：

- ✅ 明确「不收集个人数据」的本地优先声明
- ✅ 哪些「仅本地」的非个人数据会写入 localStorage
- ✅ 自动更新机制说明（仅 HTTPS 版本检查，无用户数据）
- ✅ MSIX 微软商店版本的 Microsoft 端遥测说明
- ✅ 不使用第三方分析/广告 SDK
- ✅ 数据安全、保留与删除方式
- ✅ 儿童隐私、用户权利、策略更新

### 4.5 商店页面素材

**Store listing** 块需要准备：

- 至少 1 张截图（推荐 1920×1080，PNG）
- 应用图标（512×512）
- 简短描述（≤ 200 字符）
- 详细描述（≤ 10000 字符）
- 发行说明（可选）

### 4.6 提交审核

填完所有块后，点 **Submit for certification**。状态变化：

```
Pending → Pre-processing → Certification → Publishing → In the Store
```

整个认证流程通常 **1-3 个工作日**。如果被拒，Partner Center 会告诉你具体原因（比如隐私策略 URL 不可访问、`runFullTrust` 说明不充分等），修改后重新提交即可。

## 第 5 步：首个版本过审后的 CI 自动发布

微软硬性规定：**首个版本必须手动上传**，之后版本才能通过 API 自动发布。

### 5.1 关联 Microsoft Entra ID

在 Partner Center：

1. 右上角齿轮 → **Account settings** → **Organizations**（或 Entra ID / Azure AD）
2. 关联你的 Microsoft Entra ID 租户（个人开发者可以用自己的微软账号对应的默认租户）
3. 在 Entra ID 里**注册一个应用**：Azure Portal → App registrations → New registration
4. 给这个应用赋予 Partner Center 的 **Manager** 角色

### 5.2 拿到 4 个 Secrets 值

| Secret Name | 在哪里拿 |
| --- | --- |
| `AZURE_AD_TENANT_ID` | Entra ID → 应用注册 → 概览 → **目录(租户) ID** |
| `AZURE_AD_APPLICATION_CLIENT_ID` | 同上 → **应用程序(客户端) ID** |
| `AZURE_AD_APPLICATION_SECRET` | 同上 → 证书和密码 → 新建客户端密码 → 生成的值\*\*（仅显示一次！）\*\* |
| `SELLER_ID` | Partner Center → 账户设置 → Legal Info → **Seller ID** |

### 5.3 配置 GitHub 仓库

进入仓库 **Settings → Secrets and variables → Actions**：

**🔒 Secrets（敏感信息）**：

| Name | Value |
| --- | --- |
| `AZURE_AD_TENANT_ID` | 上面的租户 ID |
| `AZURE_AD_APPLICATION_CLIENT_ID` | 上面的客户端 ID |
| `AZURE_AD_APPLICATION_SECRET` | 上面的客户端密码 |
| `SELLER_ID` | 上面的 Seller ID |

**📋 Variables（非敏感，控制开关）**：

| Name | Value |
| --- | --- |
| `MSSTORE_PACKAGE_IDENTITY_NAME` | `<你的Name>`（如 `1234567890.Tydora`） |
| `MSSTORE_PUBLISHER` | `<你的Publisher>`（如 `CN=XXXX-XXXX-...`） |
| `MSSTORE_PUBLISHER_DISPLAY_NAME` | `<你的发布者显示名>` |
| `MSSTORE_PRODUCT_ID` | Partner Center 概览页的 Store product ID（如 `9WZDNCRFXXXX`） |

> [!IMPORTANT]关键设计：在.github/workflows/msstore.yml 的发布步骤用 if: vars.MSSTORE_PRODUCT_ID 门控。只要不配 MSSTORE_PRODUCT_ID 变量，工作流只会构建 MSIX 并附到 GitHub Release，不会尝试调用 msstore publish。
> 这意味着你可以现在就推 tag 验证 MSIX 打包是否成功，等手动上架后再开启自动发布。

### 5.4 工作流文件

完整工作流 `.github/workflows/msstore.yml`，核心步骤：

```yaml
on:
  push:
    tags: ['v*']
  workflow_dispatch:

jobs:
  msix:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Node.js
        uses: actions/setup-node@v4
      - name: Install Rust stable
        uses: dtolnay/rust-toolchain@stable
      - name: Rust cache
        uses: swatinem/rust-cache@v2
      - name: Install frontend dependencies
        run: npm ci
      - name: Build MSIX
        shell: pwsh
        env:
          MSSTORE_PACKAGE_IDENTITY_NAME: ${{ vars.MSSTORE_PACKAGE_IDENTITY_NAME }}
          MSSTORE_PUBLISHER: ${{ vars.MSSTORE_PUBLISHER }}
        run: ./scripts/build-msix.ps1
      - name: Upload MSIX artifact
        uses: actions/upload-artifact@v4
        with:
          name: tydora-msix
          path: src-tauri/target/msix/*.msix
      - name: Attach MSIX to GitHub Release
        if: startsWith(github.ref, 'refs/tags/v')
        uses: softprops/action-gh-release@v2
        with:
          files: src-tauri/target/msix/*.msix
      # 以下步骤仅当配置了 MSSTORE_PRODUCT_ID 时执行
      - name: Setup Microsoft Store CLI
        if: vars.MSSTORE_PRODUCT_ID
        uses: microsoft/microsoft-store-apppublisher@v1.1
      - name: Reconfigure store credentials
        if: vars.MSSTORE_PRODUCT_ID
        run: |
          msstore reconfigure `
            --tenantId ${{ secrets.AZURE_AD_TENANT_ID }} `
            --sellerId ${{ secrets.SELLER_ID }} `
            --clientId ${{ secrets.AZURE_AD_APPLICATION_CLIENT_ID }} `
            --clientSecret ${{ secrets.AZURE_AD_APPLICATION_SECRET }}
      - name: Publish package to Store
        if: vars.MSSTORE_PRODUCT_ID
        run: |
          $msix = Get-ChildItem src-tauri/target/msix/*.msix | Select-Object -First 1
          msstore publish $msix.FullName -id ${{ vars.MSSTORE_PRODUCT_ID }}
```

### 5.5 触发发布

```bash
# 打 tag
git tag v0.1.5
git push origin v0.1.5
```

推送后 GitHub Actions 自动跑：构建 → 打包 → 上传 Release → （配了变量时）发布到商店。整个过程约 10-15 分钟。

## 踩过的坑汇总

### 坑 1：MakeAppx 报 C00CEE3B 且错误信息是乱码

**现象**：

```
MakeAppx : error: Error info: error C00CEE3B: App manifest validation error:
The app manifest XML must be valid: Line 28, Column 15, Reason: ???????????????????????????
```

**根因**：`<Properties>` 下子元素顺序不符合 `XML Schema`。正确顺序必须是 `DisplayName → PublisherDisplayName → Logo → Description`，我原来把 `Description `写在` Logo` 前面了。

**修复**：调整` AppxManifest.xml `的元素顺序。

### 坑 2：中文变乱码导致闭合标签被吃掉

**现象**：MakeAppx 仍然报 C00CEE3B，但这次是真正的 XML 解析错误。

**根因**：PowerShell 5.1 的 `Get-Content -Raw` 在文件无 BOM 时，会按系统默认编码（中文 Windows = GBK/936）解码 UTF-8 字节。具体破坏点：

- 「左瑞**宁**」的「宁」UTF-8 编码是 `E5 AE 81`
- 紧跟其后的 `<` 是 `3C`
- GBK 把 `81 3C` 当作一个合法双字节汉字 → **吃掉了** `<`
- 导致 `</PublisherDisplayName>` 变成 `?/PublisherDisplayName>`，XML 闭合标签失效

**修复**：在 `build-msix.ps1` 里把 `Get-Content -Raw` 改成 `[System.IO.File]::ReadAllText(path, [System.Text.Encoding]::UTF8)`，并给 `AppxManifest.xml` 加 UTF-8 BOM。

### 坑 3：Identity Name 不匹配

**现象**：

```
无效的软件包标识名称: Tydora (应为: <你的Name>)
无效的软件包发布者名称: CN=Tydora (应为: <你的Publisher>)
```

**根因**：`.env` 里的值带了引号和前导空格：

```dotenv
MSSTORE_PACKAGE_IDENTITY_NAME = " <你的Name>"
```

Tydora 的 `loadEnv` 解析器不剥引号，导致实际传给 MakeAppx 的 Name 是带引号带空格的字符串，触发 Partner Center 校验失败。

**修复**：`.env` 里去掉引号和 `=` 两边的空格：

```dotenv
MSSTORE_PACKAGE_IDENTITY_NAME=<你的Name>
```

### 坑 4：PublisherDisplayName 不匹配

**现象**：

```
应用清单中的 PublisherDisplayName 元素是 Tydora，该值与发布者显示名称: <你的发布者显示名> 不匹配
```

**根因**：Partner Center 注册时填的发布者显示名（个人账号默认用真实姓名），但 manifest 模板里硬编码了「Tydora」。

**修复**：把 `PublisherDisplayName` 改成占位符 `{{PUBLISHER_DISPLAY_NAME}}`，由脚本从 `.env` 注入。

### 坑 5：本地双击未签名 MSIX 报 0x800B010A

**现象**：商店模式打的包，本地双击显示「发布者: 未知」，安装按钮灰色，报错 `0x800B010A`。

**根因**：不是坑，是**预期行为**。商店模式的包本来就不签名，只应该上传到 Partner Center，由微软统一签名后分发。

**解决**：如果只是想本地测试安装效果，用本地模式（注释掉 `.env` 里的 `MSSTORE_*` 三行）打一个自签名的包即可。

## 常用命令速查

```powershell
# 完整打包（含 Rust 编译）
npm run tauri build:msix

# 跳过编译，仅重新打包
npm run tauri build:msix -- -SkipBuild

# 跳过签名
npm run tauri build:msix -- -SkipBuild -NoSign

# 强制在商店模式下也签名（用于本地安装商店身份的包做视觉验证）
npm run tauri build:msix -- -SkipBuild -Sign

# 本地测试模式（不配 MSSTORE_* 变量）
Remove-Item Env:MSSTORE_PACKAGE_IDENTITY_NAME, Env:MSSTORE_PUBLISHER, Env:MSSTORE_PUBLISHER_DISPLAY_NAME -ErrorAction SilentlyContinue
npm run tauri build:msix -- -SkipBuild
```

## 相关文档

- \[\[01-开始使用/隐私策略\]\] —— 微软商店要求的隐私策略页
- \[\[08-高级功能/01-发布网站\]\] —— Tydora 内置的静态网站发布功能
- \[\[08-高级功能/04-自动更新配置\]\] —— GitHub Releases 自动更新签名配置
- \[\[01-开始使用/02-关于\]\] —— Tydora 版本信息与技术栈

## 参考资料

- [Publishing app updates to Microsoft Store with GitHub Actions](https://learn.microsoft.com/en-us/windows/apps/publish/msstore-dev-cli/github-actions?tabs=msix)
- [MakeAppx.exe 文档](https://learn.microsoft.com/zh-cn/windows/win32/appxpkg/make-appx-package--makeappx-exe-)
- [App package manifest schema reference](https://learn.microsoft.com/en-us/uwp/schemas/appxpackage/uapmanifestschema/schema-root)
- [Microsoft Store submission API](https://learn.microsoft.com/en-us/windows/uwp/monetize/create-and-manage-submissions)