外部の場所でパッケージ化してパッケージ ID を付与する

既存のデスクトップ アプリがあり、独自のインストーラーがある場合は、パッケージ ID を利用するために変更する必要はほとんどありません。

バックグラウンド タスク、通知、ライブ タイル、カスタム コンテキスト メニュー拡張機能、共有ターゲットなど、Windows 拡張機能の多くは、実行時にデスクトップ アプリにパッケージ ID が指定されている場合にのみ、そのアプリで使用できます。 これは、オペレーティング システム (OS) で対応する API の呼び出し元を識別できる必要があるためです。 「パッケージ ID が必要な機能」を参照してください。

パッケージ アプリにのみ、実行時にパッケージ ID が含まれます。 パッケージ アプリ、非パッケージ アプリ、および外部の場所でパッケージ化されたアプリの定義については、「展開の概要」を参照してください。

  • Windows 10 バージョン 2004 以前では、パッケージ ID をアプリに付与する唯一の方法は、署名済みの MSIX パッケージでパッケージ化することです (「コードからの MSIX パッケージの構築」を参照)。 この場合、ID はパッケージ マニフェストに指定され、ID 登録はマニフェストの情報に基づいて MSIX 展開パイプラインによって処理されます。 パッケージ マニフェストで参照されるすべてのコンテンツは、MSIX パッケージ内に存在します。
  • 一方、Windows 10 バージョン 2004 以降では、アプリで "外部の場所のパッケージ" をビルドして登録するだけで、アプリにパッケージ ID を付与できます。 これにより、パッケージ アプリになります。具体的には、"外部の場所でパッケージ化されたアプリ" です。 これは、一部のデスクトップ アプリでは、すべてのコンテンツが MSIX パッケージ内に存在する準備ができていないためです。 そのため、このサポートにより、このようなアプリはパッケージ ID を持つことができ、結果としてパッケージ ID を必要とする Windows 拡張機能を使用できるようになります。 背景情報の詳細については、ブログ記事「非パッケージ Win32 アプリの ID、登録、アクティブ化」を参照してください。

外部の場所のパッケージをビルドして登録する (アプリにパッケージ ID を付与する) には、次の手順に従います。

  1. 外部の場所のパッケージのパッケージ マニフェストを作成する
  2. 外部の場所のパッケージをビルドして署名する
  3. デスクトップ アプリケーション マニフェストにパッケージ ID メタデータを追加する
  4. 実行時に外部の場所のパッケージを登録する

重要な概念

次の機能を使用すると、非パッケージ デスクトップ アプリでパッケージ ID を取得できます。

外部の場所のパッケージ

"外部の場所のパッケージ" にはパッケージ マニフェストが含まれていますが、他のアプリ バイナリやコンテンツは含まれていません。 外部の場所のパッケージのマニフェストでは、事前に定義された外部の場所で、パッケージ外部のファイルを参照できます。 前述のように、このサポートにより、すべてのコンテンツが MSIX パッケージ内に存在する準備ができていないアプリで、パッケージ ID を必要とする Windows 拡張機能を使用できます。

注意

外部の場所のパッケージを使用するデスクトップ アプリでは、MSIX パッケージを使用して完全に展開される場合の利点の一部が得られません。 これらの利点には、改ざん防止、ロックダウンされた場所へのインストール、展開、実行時、およびアンインストール時の OS による完全な管理などがあります。

外部コンテンツの許可

外部の場所のパッケージをサポートするために、パッケージ マニフェスト スキーマでは、Properties 要素の下にある省略可能な uap10:AllowExternalContent 要素がサポートされるようになりました。 これにより、パッケージ マニフェストでは、ディスク上の特定の場所にあるパッケージ外部のコンテンツを参照できます。

たとえば、アプリの実行可能ファイルとその他のコンテンツを C:\Program Files\MyDesktopApp にインストールする、既存の非パッケージ デスクトップ アプリがある場合は、マニフェスト内に uap10:AllowExternalContent 要素を含む外部の場所のパッケージを作成できます。 ご自分のアプリのインストール中、またはアプリの初回起動時に、外部の場所のパッケージをインストールし、アプリで使用する外部の場所として C:\Program Files\MyDesktopApp\ を宣言することができます。

外部の場所のパッケージのパッケージ マニフェストを作成する

外部の場所のパッケージをビルドするには、まず、デスクトップ アプリのパッケージ ID メタデータとその他の必要な詳細を宣言するパッケージ マニフェスト (AppxManifest.xml という名前のファイル) を作成する必要があります。 外部の場所のパッケージのパッケージ マニフェストを作成する最も簡単な方法は、下の例を用いて、スキーマ参照を使用してアプリ用にカスタマイズすることです。

パッケージ マニフェストに次の項目が含まれることを確認してください。

  • デスクトップ アプリの ID 属性を記述する Identity 要素。
  • Properties 要素の下にある uap10:AllowExternalContent 要素。 この要素には値 true を割り当てる必要があります。これにより、パッケージ マニフェストでは、ディスク上の特定の場所にあるパッケージ外部のコンテンツを参照できます。 後の手順で、インストーラーまたはアプリで実行されるコードから外部の場所のパッケージを登録するときに、外部の場所のパスを指定します。 パッケージ自体には存在しないマニフェスト内で参照するすべてのコンテンツは、外部の場所にインストールする必要があります。
  • TargetDeviceFamily 要素の MinVersion 属性は、10.0.19000.0 以降のバージョンに設定する必要があります。
  • Application 要素の TrustLevel=mediumIL 属性と RuntimeBehavior=Win32App 属性では、外部の場所のパッケージに関連付けられているデスクトップ アプリが、レジストリとファイル システムの仮想化やその他の実行時の変更なしに、パッケージ化されていない標準のデスクトップ アプリと同様に動作することが宣言されます。

次の例は、外部の場所のパッケージ マニフェスト (AppxManifest.xml) の完全な内容を示しています。 このマニフェストには、パッケージ ID を必要とする windows.sharetarget 拡張機能が含まれます。

<?xml version="1.0" encoding="utf-8"?>
<Package 
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2"
  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
  xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
  xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
  xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
  IgnorableNamespaces="uap uap2 uap3 rescap desktop uap10">
  <Identity Name="ContosoPhotoStore" ProcessorArchitecture="x64" Publisher="CN=Contoso" Version="1.0.0.0" />
  <Properties>
    <DisplayName>ContosoPhotoStore</DisplayName>
    <PublisherDisplayName>Contoso</PublisherDisplayName>
    <Logo>Assets\storelogo.png</Logo>
    <uap10:AllowExternalContent>true</uap10:AllowExternalContent>
  </Properties>
  <Resources>
    <Resource Language="en-us" />
  </Resources>
  <Dependencies>
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.19000.0" MaxVersionTested="10.0.19000.0" />
  </Dependencies>
  <Capabilities>
    <rescap:Capability Name="runFullTrust" />
    <rescap:Capability Name="unvirtualizedResources"/>
  </Capabilities>
  <Applications>
    <Application Id="ContosoPhotoStore" Executable="ContosoPhotoStore.exe" uap10:TrustLevel="mediumIL" uap10:RuntimeBehavior="win32App"> 
      <uap:VisualElements AppListEntry="none" DisplayName="Contoso PhotoStore" Description="Demonstrate photo app" BackgroundColor="transparent" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png">
        <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" Square310x310Logo="Assets\LargeTile.png" Square71x71Logo="Assets\SmallTile.png"></uap:DefaultTile>
        <uap:SplashScreen Image="Assets\SplashScreen.png" />
      </uap:VisualElements>
      <Extensions>
        <uap:Extension Category="windows.shareTarget">
          <uap:ShareTarget Description="Send to ContosoPhotoStore">
            <uap:SupportedFileTypes>
              <uap:FileType>.jpg</uap:FileType>
              <uap:FileType>.png</uap:FileType>
              <uap:FileType>.gif</uap:FileType>
            </uap:SupportedFileTypes>
            <uap:DataFormat>StorageItems</uap:DataFormat>
            <uap:DataFormat>Bitmap</uap:DataFormat>
          </uap:ShareTarget>
        </uap:Extension>
      </Extensions>
    </Application>
  </Applications>
</Package>

外部の場所のパッケージをビルドして署名する

パッケージ マニフェストを作成したら、Windows SDK の MakeAppx.exe ツールを使用して、外部の場所のパッケージをビルドします。 外部の場所のパッケージにはマニフェストで参照されるファイルが含まれていないため、パッケージのセマンティック検証をスキップする /nv オプションを指定する必要があります。

次の例は、コマンド ラインから外部の場所のパッケージを作成する方法を示しています。

MakeAppx.exe pack /d <path to directory that contains manifest> /p <output path>\MyPackage.msix /nv

外部の場所のパッケージがターゲット コンピューターに正常にインストールされるようにするには、ターゲット コンピューター上で信頼されている証明書を使用してそのパッケージに署名する必要があります。 開発目的の新しい自己署名証明書を作成し、Windows SDK で使用できる SignTool を使用して外部の場所のパッケージに署名することができます。

次の例は、コマンド ラインから外部の場所のパッケージに署名する方法を示しています。

SignTool.exe sign /fd SHA256 /a /f <path to certificate>\MyCertificate.pfx /p <certificate password> <path to package with external location>\MyPackage.msix

デスクトップ アプリケーション マニフェストにパッケージ ID メタデータを追加する

デスクトップ アプリケーションにサイド バイ サイド アプリケーション マニフェストを含める必要もあります。 「アプリケーション マニフェスト」を参照してください (これは DPI 認識などを宣言するファイルで、ビルド中にアプリの .exe に埋め込まれます)。 このファイルに、アプリの ID 属性を宣言する属性を持つ msix 要素を含めます。 これらの属性の値は、実行可能ファイルの起動時にアプリの ID を決定するために OS によって使用されます。

次の例は、msix 要素を含むサイドバイサイド アプリケーション マニフェストを示しています。

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="Contoso.PhotoStoreApp"/>
  <msix xmlns="urn:schemas-microsoft-com:msix.v1"
          publisher="CN=Contoso"
          packageName="ContosoPhotoStore"
          applicationId="ContosoPhotoStore"
        />
</assembly>

msix 要素の属性は、外部の場所のパッケージのパッケージ マニフェストの次の値と一致する必要があります。

  • packageName 属性と publisher 属性はそれぞれ、パッケージ マニフェストの Identity 要素の Name 属性と Publisher 属性と一致する必要があります。
  • applicationId 属性は、パッケージ マニフェストの Application 要素の Id 属性と一致する必要があります。

実行時に外部の場所のパッケージを登録する

デスクトップ アプリにパッケージ ID を付与するには、PackageManager クラスの AddPackageByUriAsync メソッドを使用して、外部の場所のパッケージを登録する必要があります。 このメソッドは、Windows 10 バージョン 2004 以降で使うことができます。 アプリを初めて実行するときに外部の場所のパッケージを登録するコードをアプリに追加したり、デスクトップ アプリのインストール中にパッケージを登録するコードを実行したりできます (たとえば、MSI を使用してデスクトップ アプリをインストールする場合、カスタム アクションからこのコードを実行できます)。

次の例では、外部の場所のパッケージを登録する方法を示します。 このコードでは AddPackageOptions オブジェクトが作成されます。このオブジェクトには、パッケージ マニフェストがパッケージ外部のコンテンツを参照できる外部の場所へのパスが含まれています。 次に、このオブジェクトが AddPackageByUriAsync メソッドに渡されて、外部の場所のパッケージが登録されます。 また、このメソッドは、署名された外部の場所のパッケージの場所を URI として受け取ります。 より完全な例については、関連するサンプル アプリの StartUp.cs コード ファイルを参照してください (このトピックの「サンプル アプリ」セクションを参照してください)。

private static bool registerPackageWithExternalLocation(string externalLocation, string pkgPath)
{
    bool registration = false;
    try
    {
        Uri externalUri = new Uri(externalLocation);
        Uri packageUri = new Uri(pkgPath);

        Console.WriteLine("exe Location {0}", externalLocation);
        Console.WriteLine("msix Address {0}", pkgPath);

        Console.WriteLine("  exe Uri {0}", externalUri);
        Console.WriteLine("  msix Uri {0}", packageUri);

        PackageManager packageManager = new PackageManager();

        // Declare use of an external location
        var options = new AddPackageOptions();
        options.ExternalLocationUri = externalUri;

        Windows.Foundation.IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = packageManager.AddPackageByUriAsync(packageUri, options);

        // Other progress and error-handling code omitted for brevity...
    }
}

サンプル アプリ

外部の場所のパッケージを使用してデスクトップ アプリにパッケージ ID を付与する方法を示す、完全な機能を備えたサンプル アプリについては、SparesePackages のサンプルを参照してください。 サンプルのビルドと実行の詳細については、ブログ記事「非パッケージ Win32 アプリの ID、登録、アクティブ化」を参照してください。

このサンプルには、次の項目が含まれます。

  • PhotoStoreDemo という名前の WPF アプリのソース コード。 起動時に、アプリが ID を使用して実行されているかどうかが確認されます。 ID を使用して実行されていない場合は、外部の場所のパッケージが登録され、アプリが再起動されます。 これらの手順を実行するコードについては、StartUp.cs を参照してください。
  • PhotoStoreDemo.exe.manifest という名前のサイドバイサイド アプリケーション マニフェスト。
  • AppxManifest.xml という名前のパッケージ マニフェスト。