UWPのカスタム機能(Custom capabilities)を使うための準備/MSとの手続き/SCCDファイル

もくじ
https://tera1707.com/entry/2022/02/06/144447

やりたいこと

あるとき、UWPの「カスタム機能」の中に含まれるUWPのAPIを使いたいときがあった。
カスタム機能とは、下記の一覧に列挙されている機能のこと。

learn.microsoft.com

例えば、カスタム機能「ESim management」に含まれる「ESim.ResetAsync」メソッドを使いたい。

ただ、なにも準備せずAPIを呼ぼうとしても、呼ぶことができなかった。
(具体的には、ESimManager.TryCreateESimWatcher()メソッドで、ESimWatcherのインスタンスがCreateできず、nullになった)

これを使おうと思うと、下記のページにあるように、Signed custom capability Descriptor(SCCD)を作成して、それにMicrosoftに署名をしてもらい、作成するアプリに組み込む必要があるらしい。

アプリ機能の宣言(機能の一覧)
https://learn.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations#custom-capabilities

ハードウェア サポート アプリ (HSA): ドライバー開発者向けの手順
https://learn.microsoft.com/en-us/windows-hardware/drivers/devapps/hardware-support-app--hsa--steps-for-driver-developers

ハードウェア サポート アプリ (HSA): アプリ開発者向けの手順
https://learn.microsoft.com/en-us/windows-hardware/drivers/devapps/hardware-support-app--hsa--steps-for-app-developers

今回、Microsoftのドキュメントに断片的に散らばっているSCCD作成の手順とアプリへの組み込み方を色々調べたので、それをメモしておく。

※少々本題と関係ない話になるが、
Microsoftのドキュメント、相変わらず情報が断片的で難しいのだが、VSCode+githubcopilotで「Microsoft learn」のMCPサーバーを使うと、断片的な情報をある程度まとめて教えてくれるので、多少は楽だった気がする。(でもやはり嘘が多かったので、情報の取捨選択はだいぶ必要だった。)

実験前提

  • VS2026 community
  • UWPアプリテンプレート

カスタム機能とは?

UWPアプリには、いろいろな機能を持たせることができる。
UWPアプリに詳しくないのだが、UWPでは、機能によっては使うためにMSに申請を行ってOKをもらわないと使えないものがある様子。

機能の括りとしては、以下がある様子。

  • 汎用機能(General-use capabilities)
    • 音楽、写真、ビデオ、ストレージなど
    • 使う場合、マニフェストに記載が必要
      (記載方法はこちら)
  • デバイス機能(Device capabilities)
    • WebCam、Microphone、Bluetoothなど
    • 使う場合、マニフェストに記載が必要 (記載方法はこちら
  • 制限された機能(Restricted capabilities)
    • Enterprise Shared Storage、System Input Injectionなど
    • 正直、よくわからない。
    • 使う場合、以前はサポートへの問い合わせが必要だったが、今はパートナーセンターで申請できるらしい(今回は調べない)
  • カスタム機能(Custom capabilities)★
    • eSIM管理など。今回はこれを調べる。

今回のeSIMのメソッドは、上記のうちの「カスタム機能」に属していた。

なので、開発するアプリでカスタム機能が使えるように申請を行う必要があった。

※デバイス機能とカスタム機能は、同じ申請を行う必要があるらしい。→こちらに書かれている

で、上のドキュメントによると、申請には「SCCDファイル」というものを書いて、それをMSに送る必要があった。

SCCD(SCCDファイル)とは?

SCCD(signed-custom-capability-descriptor)は、以下の情報を記述したxml形式のファイル。

  • Package Family Name(PFN)
  • カスタム機能名(Custom Capability Name)
  • 署名ハッシュ

これの下書きを自分で書いて、それをMSの所定のメアドに添付して送り、申請をお願いする。(英語)
申請が通ったら、下書きSCCDファイルに署名がされたものが返送されてくるので、それをアプリに取り込んで、アプリを動かすと、eSIM機能が使えるようになる。

MSDocsのサンプルは、以下の通り。

<?xml version="1.0" encoding="utf-8"?>
<CustomCapabilityDescriptor xmlns="http://schemas.microsoft.com/appx/2018/sccd" xmlns:s="http://schemas.microsoft.com/appx/2018/sccd">
<CustomCapabilities>
    <CustomCapability Name="microsoft.hsaTestCustomCapability_q536wpkpf5cy2"></CustomCapability>
</CustomCapabilities>
<AuthorizedEntities AllowAny="true"/>
<Catalog>0000</Catalog>
</CustomCapabilityDescriptor>

使用するコード

今回、下記のコードを作成・使用した。

github.com

UWPで、SCCDを作成&exeに取り込み、eSIMの機能を使う実験アプリ。 但し、本当の申請は個人ではできない(できるのかもしれないが、きっと通らない)ので、個人の実験では「開発者用のSCCDで動かす」ところまでをためした。

C#コード

ESimの操作をする部分のコードは下記のようになっている。

using System;
using System.Diagnostics;
using Windows.Networking.NetworkOperators;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace App1
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void Page_Loaded(object sender, RoutedEventArgs e)
        {
            var watcher = ESimManager.TryCreateESimWatcher();
            if (watcher != null)
            {
                watcher.Added += async (s, esim) =>
                {
                    // eSIM が見つかった時の処理
                    var resetResult = await esim.ESim.ResetAsync();

                    if (resetResult.Status == ESimOperationStatus.Success)
                        Debug.WriteLine("リセット成功");
                    else
                        Debug.WriteLine("リセット失敗");
                };

                watcher.EnumerationCompleted += (s, args) =>
                {
                    // 列挙完了
                    watcher.Stop();
                    Debug.WriteLine("列挙完了");
                };

                watcher.Start();
            }
        }
    }
}

パッケージのマニフェスト

また、UWPアプリのマニフェストを下記のようにしておく。

項目名 備考
パッケージ名 MyCompany.App1 本来は、会社名.アプリ名のように書く
発行者共通名 CN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 本来は、CN=発行者共通名のように書く
storeのパートナーポータルに登録する値?要確認

Package.appxmanifest👇

<?xml version="1.0" encoding="utf-8"?>

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  IgnorableNamespaces="uap mp">

  <Identity
    Name="MyCompany.App1"  ★ココ★
    Publisher="CN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"   ★ココ★
    Version="1.0.0.0" />

  <mp:PhoneIdentity PhoneProductId="805cedcf-d7b3-49e7-8b4b-50d746756184" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

  <Properties>
    <DisplayName>App1</DisplayName>
    <PublisherDisplayName>MyCompany</PublisherDisplayName>
    <Logo>Assets\StoreLogo.png</Logo>
  </Properties>

  <Dependencies>
    <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
  </Dependencies>

  <Resources>
    <Resource Language="x-generate"/>
  </Resources>

  <Applications>
    <Application Id="App"
      Executable="$targetnametoken$.exe"
      EntryPoint="App1.App">
      <uap:VisualElements
        DisplayName="App1"
        Square150x150Logo="Assets\Square150x150Logo.png"
        Square44x44Logo="Assets\Square44x44Logo.png"
        Description="App1"
        BackgroundColor="transparent">
        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
        <uap:SplashScreen Image="Assets\SplashScreen.png" />
      </uap:VisualElements>
    </Application>
  </Applications>

  <Capabilities>
    <Capability Name="internetClient" />
  </Capabilities>
</Package>

仮SCCDの作成&アプリに組み込んで動かす方法

今回うまくいったときの手順をメモする。

アプリのマニフェストに、使うカスタム機能のIDを書く

UWPアプリのManifest.appxmanifestに、カスタム機能名を書く。

eSIM管理機能を使うためのカスタム機能名は、こちらの一覧から、Microsoft.eSIMManagement_8wekyb3d8bbweなので、それを書く。

下記のようにする。

<?xml version="1.0" encoding="utf-8"?>

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  xmlns:uap4="http://schemas.microsoft.com/appx/manifest/uap/windows10/4" ★追加
  IgnorableNamespaces="uap mp">

・・・・・

  <Capabilities>
    <Capability Name="internetClient" />
    <uap4:CustomCapability Name="Microsoft.eSIMManagement_8wekyb3d8bbwe"/> ★追加
  </Capabilities>
</Package>

UWPアプリに自己署名しpfxファイルを作る ~ アプリパッケージ作成

pfxは、自己署名の秘密鍵と公開鍵の両方が入ったファイル。

pfxファイルは、UWPアプリの「公開」=パッケージの作成作業の流れの中で行う。
流れは以下のとおり。

・・・

ソリューションエクスプローラーでアプリのプロジェクトを右クリック > [公開] > [アプリパッケージの作成] を押す。

再度ローディングを選ぶ。

証明書を選択します、で、署名を「作成」ボタンを押す

「発行者共通名」の欄に、Manifest.appxmanifestに書いた発行者共通名を書く。
(発行者共通名とは、CN=、の右側のGUID。今回だと、"CN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" のxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxの部分)

※パスワードは本当は設定したほうがよいが、今回はナシ

これでOKを押すと、アプリ名_TemporaryKey.pfxという名前でpfxファイルが作成されて「公開」の作業に戻る。

以下で続きをやる。

アプリパッケージ作成(続き)

証明書を作るとこの画面になるので、「次へ」を押す。

設定は、通常は「Release」を選んで「作成」を押す。

パッケージの作成が始まる。作成が終わると、下のような成果物が出来上がる。

と同時に、ソリューションエクスプローラーに自己署名のpfxファイルが登録されている。
pfxが毎回変わると、今回のSCCDの運用上困る(署名が変わるとSCCDに書くハッシュの値が変わってしまう)ので、gitに登録して保存されるようにしておく。

cerファイルからハッシュ値を取得する

「公開」作業をすると、成果物のフォルダに、パッケージのファイル(.msix.msixbandleファイル)と一緒に、 .cerファイルができている。

そこから、SCCDファイルに書くための"署名のハッシュ"を取り出す。

cerからハッシュを取り出す方法は、

C:\Windows\System32\certutil.exe -dump CertificateName.cer

を実行して、こんな感じで出てきた数値。

これをメモっておく。

アプリ動作確認用の仮SCCDファイルの作成

やっと、SCCDファイルの作成に入る。

まず、UWPのプロジェクトファイルと同じ階層に「CustomCapability.sccd」という名前のファイルを作成する。
そのファイルに、

  • 使いたいカスタム機能名(Custom Capability Name) を入れる
  • AuthorizedEntities =Anyにして、一旦なんのアプリでも動くようにする
  • ESIM管理機能の場合、<CustomCapability Name="Microsoft.eSIMManagement_8wekyb3d8bbwe"></CustomCapability>を入れる

という情報を入れる。具体的には、下記の内容を書き込む。

<?xml version="1.0" encoding="utf-8"?>
<CustomCapabilityDescriptor xmlns="http://schemas.microsoft.com/appx/2018/sccd" xmlns:s="http://schemas.microsoft.com/appx/2018/sccd">
<CustomCapabilities>
    <CustomCapability Name="Microsoft.eSIMManagement_8wekyb3d8bbwe"></CustomCapability>
</CustomCapabilities>
<AuthorizedEntities>
    <AuthorizedEntity AppPackageFamilyName="MyCompany.App1_xxxxxxxxxxxxx" CertificateSignatureHash="ca9fc964db7e0c2938778f4559946833e7a8cfde0f3eaa07650766d4764e86c4"></AuthorizedEntity>
</AuthorizedEntities>
<Catalog>FFFF</Catalog>
</CustomCapabilityDescriptor>

※"MyCompany.App1_xxxxxxxxxxxxx" の後ろ13桁のxは、パブリッシャーID。本来は、自分の会社のパブリッシャーIDを入れる。 (マイクロソフトだったらeSimの機能名にもついている8wekyb3d8bbweだと思う)

  • 使いたいカスタム機能名

今回は、eSIM管理機能を使うのでその機能名を書く。

<CustomCapability Name="Microsoft.eSIMManagement_8wekyb3d8bbwe"></CustomCapability>
  • アプリ情報

AppPackageFamilyNameは、会社名.アプリ名_パブリッシャーIDの形式。
CertificateSignatureHashは、パッケージの自己署名と一緒に出力された公開鍵(cer)から取り出したハッシュを入れる。

下記のようになる。

<AuthorizedEntity AppPackageFamilyName="MyCompany.App1_xxxxxxxxxxxxx" CertificateSignatureHash="ca9fc964db7e0c2938778f4559946833e7a8cfde0f3eaa07650766d4764e86c4"></AuthorizedEntity>

CertificateSignatureHashは、上でcerファイルから取り出したハッシュ値を書く。

AuthorizedEntity とは、カスタム機能を使わせるアプリ、なので、
「このカスタム機能を使わせるアプリが、署名ハッシュがCertificateSignatureHashの値であること」という意味合いになる。

仮SCCDファイルをアプリに組み込む

UWPアプリのslnと同じ階層に、作成した「CustomCapability.sccd」をコピーする。

ソリューションエクスプローラーでそのsccdファイルを追加し、「コンテンツ」にする(コピーは不要)

これで、ビルド時にcerファイルに対応したsccdがUWPアプリに組み込まれることになる。

パッケージを作成する

「アプリパッケージ作成」の項目と同じやり方で、パッケージを作成する

※ただし、署名の作成は行わない。すでにある、ソリューションエクスプローラーにも登録した署名ファイルを使うこと。(毎回署名を変えてはいけない)

開発者モードにしたPCで動かす

仮SCCDだと、PCを「開発者モード」にしておかないと、作成したパッケージはインストールできない。 (インストール時にエラーになる)

そのためまずはPCを「開発者モード」にする。

開発者モードにしたら、アプリのappxファイルを実行し、インストールする。

インストールしたアプリを実行すると、eSIMの機能をUWPアプリから使うことができる。

動いたことの確認

具体的には、

var watcher = ESimManager.TryCreateESimWatcher();

で作成するwatcherが、SCCDをコンテンツとして組み込む前はnullになっていたのが、 組み込み後はnullではなく正しくwatcherを取れるようになる。

これで、その後の処理もうまく動くようになる。 (動いたこと(watcherがnullではなかったこと)が画面表示等でわかるようなサンプルにしておくこと。)

ここまでで、仮SCCD(テスト用SCCD)で動かす工程はOK。

アプリの実装、テストなどをしたい場合は、このSCCDを使って行っておく。

並行して、本番用SCCDの申請をマイクロソフトに投げる。

本番SCCD作成方法&アプリに組み込んで動かす方法

ここからは、本番用のSCCDの作成をする。

SCCDを添付して、メールでMSに署名を依頼する

ここ👇に、本番用SCCDを申請する場合のやり方が書いてある。

https://learn.microsoft.com/en-us/windows-hardware/drivers/devapps/hardware-support-app--hsa--steps-for-driver-developers#reserving-a-custom-capability

これに沿って、申請をする。

上記の内容を、HSAReview@microsoft.com に送って申請をする。

まずメールは英語で書くこと。

※今回私がメールしたときは、日本語と英語両方書いて、「日本語もしできるようなら日本語で連絡ください!」とかいたけど、英語で帰ってきた。

メール本文に、上記に連絡必要と書かれていた内容を書く。

「機能の名前」は、今回の場合だと「ESim管理機能」のことなので、「ESim管理機能(Microsoft.eSIMManagement_8wekyb3d8bbwe)」 などと書いておけばOK。

開発者モードで、動かしたいカスタム機能が動くことを確認できたSCCD(「アプリ動作確認用の仮SCCDファイルの作成」のところで作成した仮のSCCD)を、メールに添付する。

※もし、開発者モードでないと動かないようにしたくて<DeveloperModeOnly Value="true" />を書いていたり、どんなアプリでも使えるSCCDにしたくて<AuthorizedEntities AllowAny="true"/>を書いていたりした場合は、けしてから送った方がよいと思う。

添付したら、メールを送る。

今回は、メールで申請を送って1日くらいで、応答があった。

応答のメールには、本番用SCCDが添付されていた。
SCCDの内容は具体的な内容はここには書かないが、👇のような内容だった。

基本の内容は、送ったSCCDとおなじ。ただし以下が、MSのほうで追記/修正されている。

  • AuthorizedEntity が2つになっている。
    • 1つは自分が書いたものそのまま。自分のアプリのPFNと、自分の自己署名のハッシュが書かれたもの。
      • 本番用SCCDの動作確認用のために、自己署名分の記載も残してくれてるのだと思われる
    • 追記された2つ名は、自分のアプリのPFNと、おそらくフライト/store登録したときにMicrosoftが付ける処理のハッシュが書かれたもの。
      • MSストアでフライトしたアプリには、MSの署名が付けられる。その署名された状態で動くためのハッシュ。要はこっちが本番用ということ。
  • Catalog
    • このSCCDファイルを組み込んだアプリをPCにインストールするときに、署名とSCCDが問題ないかをチェックするときの値(だと思う)
    • これがないと、SCCDを組み込んだアプリがインストール時にエラーになる

イメージとしては、下記のような内容。
(追記されたものの値は私が適当に書いたもの。)

<?xml version="1.0" encoding="utf-8"?>
<CustomCapabilityDescriptor xmlns="http://schemas.microsoft.com/appx/2018/sccd" xmlns:s="http://schemas.microsoft.com/appx/2018/sccd">
<CustomCapabilities>
    <CustomCapability Name="Microsoft.eSIMManagement_8wekyb3d8bbwe"></CustomCapability>
</CustomCapabilities>
<AuthorizedEntities>
    <AuthorizedEntity AppPackageFamilyName="MyCompany.App1_xxxxxxxxxxxxx" CertificateSignatureHash="ca9fc964db7e0c2938778f4559946833e7a8cfde0f3eaa07650766d4764e86c4"></AuthorizedEntity>
    <AuthorizedEntity AppPackageFamilyName="MyCompany.App1_xxxxxxxxxxxxx" CertificateSignatureHash="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"></AuthorizedEntity>
</AuthorizedEntities>
<Catalog>abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg</Catalog>
</CustomCapabilityDescriptor>

本番用SCCDファイルをアプリに組み込む

これを「仮SCCDファイルをアプリに組み込む」の項と同じ方法でアプリに組み込む。

パッケージを作成する(本番用)

「アプリパッケージ作成」の項目と同じやり方で、パッケージを作成する

※ただし、仮SCCDの時と同じで、署名の作成は行わない。最初に作ったものを使う。

作ったパッケージを、フライト&ストア登録する

作ったアプリのパッケージを、マイクロソフトのパートナーポータルでフライトする。

その後は、必要に応じてstore登録などをする。

これで、カスタム機能を使うアプリの実装は完了。

思ったこと

「署名」がどういうものなのか知識が足りてなかった私にとっては、とても難しい申請だった。

自分が勝手に作る自己署名(別名:オレオレ署名)で出したcerのハッシュを、本番用でも使うためのSCCDの申請に使うなんて、、これでなにが安全になるのか?とさっぱりわからなかったが、署名とは?がわかってくると、その辺の手続きの流れの意味も少しずつ分かってきた気がする。

用語集

用語集

  • Package.appxmanifest にある情報
項目 意味
Identity の Name パッケージ名。
会社名.アプリ名のように書く。
Identity の "CN=" の=の右側 発行者共通名
"CN=xxxxxxx" CN=の部分も入れて「発行者」というらしい。
UWPテンプレのままだとCN=・・しかないが、例えばマイクロソフトの場合だと他の情報もいろいろ入ってこうなるらしい
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
  • SCCD にある情報
項目 意味
CustomCapability の Name カスタム機能名。UWPアプリから使いたい機能の名前。
こちらの一覧に載っている。
eSIM管理機能の場合はMicrosoft.eSIMManagement_8wekyb3d8bbwe
AuthorizedEntity の AppPackageFamilyName カスタム機能を使わせたいアプリのフルネームみたいなもの。PFNと略する。
会社名.アプリ名_パブリッシャーIDのような形式になる。
パブリッシャーID PFNの後ろ半分。マイクロソフトだと「8wekyb3d8bbwe」となる。
下記のような変換で、8wekyb3d8bbweができるらしい。
AuthorizedEntity の CertificateSignatureHash cerファイルから「C:\Windows\System32\certutil.exe -dump CertificateName.cer」のコマンドで取り出すハッシュ値。

参考

アプリ機能の宣言

https://learn.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations#custom-capabilities

ハードウェア サポート アプリ (HSA): ドライバー開発者向けの手順

https://learn.microsoft.com/en-us/windows-hardware/drivers/devapps/hardware-support-app--hsa--steps-for-driver-developers

ハードウェア サポート アプリ (HSA): アプリ開発者向けの手順

https://learn.microsoft.com/en-us/windows-hardware/drivers/devapps/hardware-support-app--hsa--steps-for-app-developers