Windows アプリでのパッケージ ID の概要

パッケージ ID は、空間と時間の間の一意の識別子です。 DNA によって一意に識別されるのと同様に、パッケージ ID によってパッケージが一意に識別されます。

パッケージには、一連のビット (ファイルなど) が関連付けられています。 同じ ID を持つ 2 つのパッケージはなく、パッケージに関連付けられているビットに対する変更には別の ID が必要です。

パッケージ ID とは

パッケージ ID は、パッケージを一意に識別する論理コンストラクトです。 ID には 5 つの部分があります。

  • 名: これは、アプリ開発者によって選択された名前です。 Microsoft Store では、ストア内のすべてのアプリ開発者に対してすべてのアプリ名の一意性が適用されますが、名前が一般的なエコシステムで一意であるとは限りません。
  • バージョン: パッケージのバージョン番号 アプリ開発者は任意のバージョン番号を選択できますが、更新プログラムによってバージョン番号が増える必要があります。
  • アーキテクチャ: パッケージの対象となるプロセッサ アーキテクチャ。 同じアプリは、異なるプロセッサ アーキテクチャを対象としてビルドでき、各ビルドは独自のパッケージに存在します。
  • ResourceId: さまざまな言語や異なる表示スケールなど、リソース パッケージを一意に識別するためにアプリ開発者によって選択された文字列。 通常、リソース パッケージはアーキテクチャに依存しません。 バンドルの場合、ResourceId は常に ~
  • パブリッシャー: 署名証明書によって識別されるアプリ開発者のサブジェクト名。 信頼できる証明機関は一意の実際の名前と ID を使用して証明書のサブジェクト名フィールドを設定するため、これは理論的にはアプリ開発者ごとに一意です。

このコンストラクトは、5 部構成のタプルと呼ばれることもあります。

署名されていないパッケージ (1) には、引き続き Publisherが必要です。(2) Publisher には、署名されていないマーカー (OID.2.25.311729368913984317) が含まれている必要があります 654407730594956997722=1)、(3) 署名されていないマーカー Publisher 文字列の最後のフィールドである必要があり、(4) 署名されていないパッケージの証明書または署名がない。

パッケージ ID フィールドの制限

フィールド データの種類 制限 コメント
名前 パッケージ文字列 最小: 3
最大: 50
Validate API ごとに使用できる値 (パッケージ文字列参照)
Version DotQuad 最小: 0.0.0.0
最大: 65535.65535.65535.65535
文字列形式では、Base-10 のドット表記 "Major.Minor.Build.Revision" が使用されます
アーキテクチャ 列挙 最小: N/A
最大: N/A
使用できる値は、"neutral"、"x86"、"x64"、"arm"、"arm64"、"x86a64" です。
リソースID パッケージ文字列 最小: 0
最大: 30
Validate API ごとに使用できる値 (パッケージ文字列参照)
発行者 最小: 1
最大: 8192
X.509 あたりの使用可能な値
パブリッシャーID 最小: 13
最大: 13
Base32 でエンコードされた、Crockford バリアント、つまり [a-hjkmnp-tv-z0-9]

"パッケージ文字列" とは

パッケージ文字列 は、次の文字を使用できる文字列です。

  • 許可される入力文字 (ASCII サブセット)
    • 大文字 (U+0041 から U+005A)
    • 小文字 (U+0061 から U+007A まで)
    • 数値 (U+0030 ~ U+0039)
    • ドット (U+002E)
    • ダッシュ (U+002D)

次の値は、パッケージ文字列として使用できません。

条件 禁止値
等しくない "."、".."、"con"、"prn"、"aux"、"nul"、"com1"、"com2"、"com3"、"com4"、"com5"、"com6"、"com7"、"com8"、"com9"、"lpt1"、"lpt2"、"lpt3"、"lpt4"、"lpt5"、"lpt6"、"lpt7"、"lpt8"、"lpt9"
先頭を次の値にすることは不可 "con."、"prn."、"aux."、"nul."、"com1."、"com2."、"com3."、"com4."、"com5."、"com6."、"com7."、"com8."、"com9."、"lpt1."、"lpt2."、"lpt3."、"lpt4."、"lpt5."、"lpt6."、"lpt7."、"lpt8."、"lpt9."、"xn--"
末尾を次の値にすることは不可 "."
を含めることはできません ".xn--"

パッケージ文字列 は、大文字と小文字を区別しない序数の文字列比較 API (_wcsicmp など) を使用して比較する必要があります。

Package Identity の name フィールドと resourceid フィールドはパッケージ文字列です。

PackageId オブジェクト

PackageId は、5 部構成のタプルを個々のフィールド (NameVersionArchitectureResourceIdPublisher) として含むオブジェクトです。

パッケージの完全な名前

パッケージのフル ネーム は、パッケージの ID (名前、バージョン、アーキテクチャ、リソース ID、発行元) の 5 つの部分すべてから派生した不透明な文字列です。

<Name>_<Version>_<Architecture>_<ResourceId>_<PublisherId>

たとえば、Windows フォト アプリの 1 つのパッケージフル ネームは "Microsoft.Windows.Photos_2020.20090.1002.0_x64__8wekyb3d8bbwe" です。 ここで、"Microsoft.Windows.Photos" は名前、"2020.20090.1002.0" はバージョン番号、"x64" はターゲット プロセッサ アーキテクチャ、リソース ID は空 (最後の 2 つのアンダースコア間のコンテンツなし)、"8wekyb3d8bbwe" は Microsoft の発行元 ID です。

パッケージのフル ネーム は、MSIX パッケージまたはバンドルを一意に識別します。 2 つのパッケージまたはバンドルの内容が異なるが、パッケージのフル ネームが同じであると、エラーになります。

MSIX は、前の用語 APPXの新しい名前です。 詳細については、「MSIX とは」を参照してください。

パッケージ ファミリ名

パッケージ ファミリ名 は、パッケージ ID の 2 つの部分 (名前 とパブリッシャー) から派生した不透明な文字列です。

<Name>_<PublisherId>

たとえば、Windows フォト アプリのパッケージ ファミリ名は "Microsoft.Windows.Photos_8wekyb3d8bbwe" で、"Microsoft.Windows.Photos" は名前、"8wekyb3d8bbwe" は Microsoft の発行元 ID です。

パッケージ ファミリ名は、多くの場合、"バージョンレスパッケージフルネーム" と呼ばれます。

パッケージ ファミリ名にもアーキテクチャとリソース ID がないため、これは厳密には当てはまりません。

通常、データとセキュリティはパッケージ ファミリに限定されています。 たとえば、メモ帳バージョン 1.0.0.0 パッケージからインストールされたメモ帳アプリを Wordwrap を有効にするように構成した場合、エクスペリエンスが低下します。 その後、メモ帳が 1.0.0.1 に更新され、構成データがパッケージの新しいバージョンに引き継がれませんでした。

パブリッシャー ID

パッケージ ファミリ名は、次の形式の文字列です。

<name>_<publisherid>

パブリッシャー ID には、いくつかの非常に具体的なプロパティがあります。

  • 公開元から派生
  • MinLength = MaxLength = 13 文字 [固定サイズ]
  • 使用できる文字 (正規表現) = a-hj-km-np-tv-z0-9
    • Base-32、Crockford バリアント (つまり、I (アイ)、L (エル)、O (オー) または U (ユー) 以外の英数字 (A-Z0-9))
  • 順次比較で大文字と小文字を区別しない --- ABCDEFABCDEFG == abcdefabcdefg

だから、あなたは % を見ることはありません: \ / " ? 文字は表示されません。

詳細については、PackageFamilyNameFromIdPackageNameAndPublisherIdFromFamilyName を参照してください。

パブリッシャー ID は、多くの場合、PublisherId と呼ばれます。

パブリッシャー ID が存在する理由

パブリッシャー ID が存在するのは、発行元が証明書の X.509 名/署名者と一致する必要があるためです。したがって、次のようになります。

  • 非常に大きい場合があります (長 <= 8192 文字)
  • これには、ぎこちない文字や制限された文字 (円記号など) を含めることができます。

これらの問題により、一部の X.509 文字列がファイルシステム、レジストリ、URL、およびその他のコンテキストで使用できなくなる可能性があります。

PublisherId を作成する方法

PackageNameAndPublisherIdFromFamilyName を使用して、PublisherId から PackageFamilyName を抽出します。

PackageIdFromFullName を使用して PublisherId から PackageFullName を抽出します。

PublisherIdから Publisher を作成する必要はほとんどありませんが、使用可能な API を使用して行うことができます。

#include <appmodel.h>

HRESULT PublisherIdFromPublisher(
    _In_ PCWSTR publisher,
    _Out_writes_(PACKAGE_PUBLISHERID_MAX_LENGTH + 1) PWSTR publisherId)
{
    PCWSTR name{ L"xyz" };
    const size_t nameLength{ ARRAYSIZE(L"xyz") - 1 };
    const size_t offsetToPublisherId{ nameLength + 1 }; // xyz_...publisherid...
    PACKAGE_ID id{};
    id.name = name;
    id.publisher = publisher;
 
    WCHAR familyName[PACKAGE_FAMILY_NAME_MAX_LENGTH + 1]{};
    UINT32 n{ ARRAYSIZE(familyName) };
    RETURN_IF_WIN32_ERROR(PackageFamilyNameFromId(&id, &n, familyName));
    RETURN_IF_FAILED(StringCchCopyW(publisherId, PACKAGE_PUBLISHERID_MAX_LENGTH + 1, familyName + offsetToPublisherId));
    return S_OK;
}

同じ操作の従来の Windows C 実装を次に示します。

#include <appmodel.h>

HRESULT PublisherIdFromPublisher(
    _In_ PCWSTR publisher,
    _Out_writes_(PACKAGE_PUBLISHERID_MAX_LENGTH + 1) PWSTR publisherId)
{
    const WCHAR c_name[]{ L"xyz" };
    const UINT32 c_nameLength{ ARRAYSIZE(c_name) - 1 };

    PACKAGE_ID id{};
    id.name = c_name;
    id.publisher = publisher;
    WCHAR familyName[PACKAGE_FAMILY_NAME_MAX_LENGTH + 1]{};
    UINT32 n{ ARRAYSIZE(familyName) };
    RETURN_IF_WIN32_ERROR(PackageFamilyNameFromId(&id, &n, familyName));
    RETURN_IF_FAILED(StringCchCopyW(publisherId, PACKAGE_PUBLISHERID_MAX_LENGTH + 1, familyName + c_nameLength + 1));
    return S_OK;
}

これにより、結果の形式が xyz_<publisherid>のパッケージ ファミリ名にパッケージ ID を変換して PublisherId が作成されます。 このレシピは安定しており、信頼性があります。

これには、SDK から appmodel.h を使用してコンパイルし、kernel32.lib (または、API を使用する場合は kernelbase.lib、onecore.lib、または api-ms-win-appmodel-runtime-l1.lib) を使用してリンクする必要があります。

パッケージ ID のプロセッサ アーキテクチャについて

一般的な誤解は、Architecture=x64 パッケージに x64 コードのみを含めることができるということです。 これは正しくありません。 これは、パッケージが x64 コードをサポートするシステムで動作し、x64 アプリで使用できることを意味します。 PDFファイルのみを含むパッケージを作成できますが、それを<Identity Architecture=x64...>で宣言するのは、x64互換システムへのインストールを意図しているためです。x86やArm、Windows 10 Arm64システムはx64をサポートしていないため、x64パッケージはx64および(Windows 11以降)Arm64システムにのみインストール可能です。

さらに誤解されていることとして、Architecture=neutral はパッケージに実行可能なコードが含まれていないという意味では "ありません"。 これは、パッケージがすべてのアーキテクチャで動作することを意味します。 たとえば、JavaScript、Python、C# などで記述された AES 暗号化 API を含むパッケージを作成できますが、Arm64 システムではパフォーマンスは許容されません。 そのため、最適化された Arm64 バイナリを含め、それを処理する API を実装します。

void Encrypt(...)
{
    HANDLE h{};
    if (GetCpu() == arm64)
    {
        h = LoadLibrary(GetCurrentPackagePath() + "\bin\encrypt-arm64.dll")
        p = GetProcAddress(h, "Encrypt")
        return (*p)(...)
    }
    else
    {
        // ...call other implementation...
    }
}

または、複数のバリアントを含むニュートラル パッケージを作成することもできます。

\
    bin\
        encrypt-x86.dll
        encrypt-x64.dll
        encrypt-arm.dll
        encrypt-arm64.dll

開発者は、実行時にプロセスに適したバイナリを取得するために LoadLibrary("bin\encrypt-" + cpu + ".dll") を使用できます。

通常、ニュートラル パッケージにはアーキテクチャごとのコンテンツはありませんが、可能です。 できることには制限があります (たとえば、x86 + x64 + arm + arm64 用にコンパイルされた notepad.exe を含むメモ帳パッケージを作成できますが、appxmanifest.xml はそのうちの 1 つを指す <Application Executable=...> のみを宣言できます)。 必要なビットのみをインストールできるバンドルがあることを考えると、これは非常に珍しいことです。 それは違法ではなく、ただ高度でエキゾチックです。

また、Architecture=x86 (または x64|arm|arm64) は、パッケージに指定されたアーキテクチャの実行可能コードのみが含まれていることを意味するものではありません。 これは、圧倒的に一般的なケースにすぎません。

このコンテキストで "コード" または "実行可能コード" について説明するときは、ポータブル実行可能 (PE) ファイルを参照しています。

パッケージ識別子は大文字と小文字を区別しますか?

ほとんどの場合区別されませんが、Publisher では大文字と小文字が区別されます。

残りのフィールド (NameResourceIdPublisherIdPackageFullName、および PackageFamilyName) はありません。 これらのフィールドでは大文字と小文字が保持されますが、大文字と小文字は区別されずに比較されます。

パッケージ ID とアプリケーション ID

パッケージ ID とアプリケーション ID は関連していますが、個別の概念です。 違いを理解することは 、アプリケーションがその パッケージであるという一般的な誤解を避けるのに役立ちます。

  • パッケージは、配布と展開の単位です。 パッケージ全体をインストール、更新、または削除します。
  • アプリケーションはユーザー向けのコンストラクトであり、実装方法 (単一プロセス、複数のプロセス、またはプロセスを共有する複数のアプリケーション) に関係なく、1 つのプログラムを形成するウィンドウ、プロセス、およびその他のリソースのコレクションです。

アプリケーションはパッケージ を介して 配布されますが、パッケージと同じものではありません。 1 つのパッケージで 0 から 100 までの任意の場所のアプリケーションを宣言できます。一部のパッケージの種類 ( フレームワーク パッケージリソース パッケージなど) では、アプリケーションをまったく宣言できません。

ApplicationUserModelID (AUMID)

パッケージ化されたアプリケーションの場合、アプリケーション ID は ApplicationUserModelID ( AppUserModelId または AUMID とも呼ばれます) によって表されます。 この文字列を使用すると、Windowsは、アプリケーションの内部アーキテクチャに関係なく、windows、プロセス、およびリソースを特定のアプリケーションに関連付けることができます。

つまり、次のとおりです。

  • パッケージ ID (前述の 5 部構成のタプル) は 、パッケージを一意に識別します。
  • アプリケーション ID (AUMID) は、そのパッケージ内の アプリケーション を一意に識別します。

Windowsでは、AUMID を使用して実行時にアプリケーションを推論します。たとえば、タスク バーでwindowsをグループ化したり、通知をルーティングしたり、アプリのライフサイクルを管理したりします。 AUMID はパッケージ マニフェストの Application 要素で宣言され、パッケージ ファミリ名とアプリケーションの宣言された ID から派生します。

Tip

アプリケーションがパッケージではない理由と、AUMID が 2 つの概念をどのように橋渡しするのかについて詳しくは、Inside MSIX ブログの 「アプリケーションはパッケージではない 」をご覧ください。

こちらも参照ください