次の方法で共有


外部の場所でパッケージ化されたまたはパッケージ化されていないフレームワーク依存のアプリ向け Windows App SDK 展開ガイド

このトピックでは、外部の場所でパッケージ化されたアプリ、またはパッケージ化されていないアプリ、およびWindows App SDKを使用するアプリの展開に関するガイダンスを提供します。

  • このようなアプリはデスクトップ アプリです (UWP アプリではありません)。
  • これらは、C# などの .NET 言語または C++ で記述できます。
  • ユーザー インターフェイスには、WinUI 3、WPF、WinForms、または別の UI フレームワークを使用できます。

概要

外部の場所でパッケージ化されたアプリとパッケージ化されていないアプリの開発者は、必要なWindows App SDK ランタイム パッケージをエンド ユーザーに展開する責任があります。 これを行うには、インストーラーを実行するか、MSIX パッケージを直接インストールします。 これらのオプションについては、以下の「Windows App SDK ランタイムのデプロイ」 セクションで詳しく説明します。

また、外部の場所でパッケージ化されたアプリやパッケージ化されていないアプリには、追加のランタイム要件があります。 ブートストラップ API を使用して、Windows App SDK ランタイムへのアクセスを初期化する必要があります。 さらに、アプリで Windows App SDK 以外の他のフレームワーク パッケージを使用する場合にも、動的依存関係 API を使用できます。 これらの要件については、以下の「外部の場所でパッケージ化されたアプリまたはパッケージ化されていないアプリのランタイム要件」 セクションで詳しく説明します。

前提条件

追加の前提条件

  • Windows App SDK の試験段階およびプレビュー バージョンでは、ランタイムをインストールするためにサイドローディングが有効になっている必要があります。
    • サイドローディングは、Windows 10 バージョン 2004 以降で自動的に有効になります。

    • 開発用コンピューターまたはデプロイ コンピューターで Windows 11 を実行している場合は、次の手順でサイドローディングが有効になっているかどうかを確認します。

      • 設定 > プライバシーとセキュリティ > 開発者向け。 開発者モード がオンになっていることを確認してください。
    • 開発用コンピューターまたは展開用コンピューターが Windows 10 バージョン 1909 以前のバージョンを実行している場合は、サイドローディングが有効になっているかどうかを確認します。

      • 設定 > 更新とセキュリティ > 開発者向け > 開発者向け機能を使用する。 [アプリのサイドローディング] または [開発者モード] が選択されていることを確認します。
    • 開発者モードの設定には、サイドローディングと他の機能が含まれます。

      Note

      コンピューターがエンタープライズ環境で管理されている場合は、これらの設定の変更を禁止するポリシーが存在する可能性があります。 その場合、ユーザーまたはアプリが Windows App SDK ランタイムをインストールしようとしたときにエラーが発生した場合は、IT プロフェッショナルに問い合わせて、サイドローディングまたは開発者モードを有効にしてください。

Windows App SDK ランタイムを配置する

外部の場所でパッケージ化されたアプリとパッケージ化されていないアプリには、Windows App SDK ランタイムをデプロイするための 2 つのオプションがあります。

オプション 1: インストーラーを使用する

インストーラーを実行することで、すべてのWindows App SDK ランタイム パッケージをデプロイできます。 インストーラーは、Windows App SDK のダウンロードで入手できます。 インストーラー (.exe) を実行すると、次のような出力が表示されます。

Deploying package: Microsoft.WindowsAppRuntime.1.0_0.318.928.0_x64__8wekyb3d8bbwe
Package deployment result : 0x0

Deploying package: Microsoft.WindowsAppRuntime.1.0_0.318.928.0_x86__8wekyb3d8bbwe
Package deployment result : 0x0

Deploying package: MicrosoftCorporationII.WindowsAppRuntime.Main.1.0_0.318.928.0_x64__8wekyb3d8bbwe
Package deployment result : 0x0
Provisioning result : 0x0

Deploying package: Microsoft.WindowsAppRuntime.Singleton_0.318.928.0_x64__8wekyb3d8bbwe
Package deployment result : 0x0
Provisioning result : 0x0

Deploying package: Microsoft.WinAppRuntime.DDLM.0.318.928.0-x6_0.318.928.0_x64__8wekyb3d8bbwe
Package deployment result : 0x0
Provisioning result : 0x0

Deploying package: Microsoft.WinAppRuntime.DDLM.0.318.928.0-x8_0.318.928.0_x86__8wekyb3d8bbwe
Package deployment result : 0x0
Provisioning result : 0x0

All install operations successful.

ユーザーの操作なしでインストーラーを実行し、--quiet オプションを使用してすべてのテキスト出力を抑制できます。

WindowsAppRuntimeInstall.exe --quiet

また、--force オプションを使用して、MSIX パッケージを強制的に更新し、現在実行中の Windows App SDK プロセスをシャットダウンすることもできます。 この機能は 1.1 で導入されました。

WindowsAppRuntimeInstall.exe --force

すべてのインストーラー コマンド ライン オプションを表示するには、WindowsAppRuntimeInstall --h を実行します。

インストールが完了したら、パッケージ化された外部の場所またはパッケージ化されていないアプリを実行できます。 Windows App SDK を使用する外部の場所でパッケージ化されたアプリまたはパッケージ化されていないアプリをビルドして実行する方法の例については、「チュートリアル: Windows App SDK を使用する外部の場所でパッケージ化されたアプリまたはパッケージ化されていないアプリでブートストラップ API を使用する」を参照してください。

Windows App SDK インストーラーをアプリのセットアップにチェーンする

アプリのカスタム セットアップ プログラムがある場合は、アプリのセットアップ プロセスで Windows App SDK セットアップ プロセスをチェーンできます。 Windows App SDK インストーラーでは現在、既定の UI が提供されないため、そのセットアップのカスタム UI を使用してチェーンする必要があります。

Windows App SDK のセットアップをサイレントに起動して追跡している間、ShellExecute を使用して、セットアップの進行状況の独自のビューを表示できます。 Windows App SDK インストーラーは、Windows アプリ MSIX バンドルをサイレント アンパックし、PackageManager.AddPackageAsync メソッドを呼び出してインストールを完了します。 これは、以前に使用していた可能性がある他のランタイム インストーラー (.NET、Visual C++、DirectX など) と非常によく似ています。

セットアップ プログラムから Windows App SDK インストーラーを実行する方法を示すコード例については、インストーラーの機能テストRunInstaller 関数を参照してください。

インストーラーのサンプル

セットアップ中にコンソール ウィンドウをポップアップせずに Win32 セットアップ プログラムからインストーラーを起動する方法については、次のサンプルを参照してください。

トラブルシューティング

リターン コード

次の表は、Windows App SDK .exe インストーラーの最も一般的なリターン コードの一覧を示しています。 これらのリターン コードは、すべてのバージョンのインストーラーで共通です。

リターン コード 説明
0x0 パッケージのインストールまたはプロビジョニングが正常に完了しました。
0x80073d06 1 つ以上のパッケージをインストールできませんでした。
0x80070005 アプリが管理者特権で実行されていないか、またはインストールを実行しているユーザーに管理者特権がないため、システム全体にわたるインストールまたはプロビジョニングを実行できませんでした。

インストール エラー

Windows App SDK インストーラーがインストール中にエラーを返す場合は、問題を説明するエラー コードを返します。

  • 一般的なエラー コードの一覧を参照してください。
  • エラー コードによって十分な情報が提供されない場合は、詳細なイベント ログでさらに多くの診断情報を見つけることができます。
  • 問題を調査できるように、エラー コードやイベント ログと一緒に問題を報告してください。

オプション 2: Windows App SDK ランタイム パッケージを直接デプロイする

エンド ユーザーへのデプロイのために Windows App SDK インストーラーを使用する代わりに、アプリのプログラムまたは MSI を使用して MSIX パッケージを手動でデプロイできます。 このオプションは、より細かく制御したい開発者には最適です。

セットアップ プログラムで MSIX パッケージをインストールする方法を示す例については、Windows App SDK インストーラー コードの install.cpp を参照してください。

Windows アプリ SDKが既にインストールされているかどうかを確認するには (インストールされている場合はバージョン)、PackageManager.FindPackagesForUserWithPackageTypes を呼び出して、特定のパッケージ ファミリを確認できます。

mediumIL (完全信頼) のパッケージ化されていないプロセス (Application 要素を参照) から、次のコードを使用して、現在のユーザーに登録されているパッケージを確認できます。

using Windows.Management.Deployment;

public class WindowsAppSDKRuntime
{
    public static IsPackageRegisteredForCurrentUser(
        string packageFamilyName,
        PackageVersion minVersion,
        Windows.System.ProcessorArchitecture architecture,
        PackageTypes packageType)
    {
        ulong minPackageVersion = ToVersion(minVersion);

        foreach (var p : PackageManager.FindPackagesForUserWithPackageTypes(
            string.Empty, packageFamilyName, packageType)
        {
            // Is the package architecture compatible?
            if (p.Id.Architecture != architecture)
            {
                continue;
            }

            // Is the package version sufficient for our needs?
            ulong packageVersion = ToVersion(p.Id.Version);
            if (packageVersion < minPackageVersion)
            {
                continue;
            }

            // Success.
            return true;
        }

        // No qualifying package found.
        return false;
    }

    private static ulong ToVersion(PackageVersion packageVersion)
    {
        return ((ulong)packageVersion.Major << 48) |
               ((ulong)packageVersion.Minor << 32) |
               ((ulong)packageVersion.Build << 16) |
               ((ulong)packageVersion.Revision);
    }
}

上記のシナリオでは、 FindPackagesForUserWithPackageTypes を呼び出す方が、 FindPackagesForUser を呼び出すよりも適しています。 これは、検索を (この例では) framework またはメイン パッケージに絞り込むことができるためです。 これにより、この例では関心のない他の種類のパッケージ ( resourceoptionalbundle など) の照合が回避されます。

現在または呼び出し元のユーザー コンテキストを使用するには、 userSecurityId パラメーターを空の文字列に設定します。

ここで、上記のコード例で関数を呼び出す 方法 決定するのに役立つ情報を示します。 適切にインストールされたランタイムは、システムの CPU アーキテクチャに依存する複数のパッケージで構成されます。

  • x86 コンピューターの場合: Fwk=[x86]、Main=[x86]、Singleton=[x86]、DDLM=[x86]。
  • x64 コンピューターの場合: Fwk=[x86, x64], Main=[x64], Singleton=[x64], DDLM=[x86, x64]。
  • arm64 コンピューターの場合: Fwk=[x86, x64, arm64], Main=[arm64], Singleton=[arm64], DDLM=[x86, x64, arm64]。

Main パッケージと Singleton パッケージのアーキテクチャは、システムの CPU アーキテクチャ (x64 システム上の x64 パッケージなど) と一致している必要があります。 Framework パッケージの場合、x64 システムは x64 アプリと x86 アプリの両方を実行できます。同様に、arm64 システムは arm64、x64、および x86 アプリを実行できます。 DDLM パッケージ チェックは、Framework チェックに似ていますが、PackageType=mainpackagefamilynameが異なり、DDLM固有の名前付けスキームにより、複数の (異なる) packagefamilynameを適用できます。 詳細については、 MSIX パッケージ 仕様を参照してください。そのため、チェックは次のようになります。

public static bool IsRuntimeRegisteredForCurrentUser(PackageVersion minVersion)
{
    ProcessorArchitecture systemArchitecture = DetectSystemArchitecture();

    return IsFrameworkRegistered(systemArchitecture, minVersion) &&
           IsMainRegistered(systemArchitecture, minVersion) &&
           IsSingletonRegistered(systemArchitecture, minVersion) &&
           IsDDLMRegistered(systemArchitecture, minVersion);
}

private static ProcecssorArchitecture DetectSystemArchitecture()
{
    // ...see the call to IsWow64Process2(), and how the result is used...
    // ...as per `IsPackageApplicable()` in
    // [install.cpp](https://github.com/microsoft/WindowsAppSDK/blob/main/installer/dev/install.cpp)
    // line 99-116...
    // ...WARNING: Use IsWow64Process2 to detect the system architecture....
    // ...         Other similar APIs exist, but don't give reliably accurate results...
}

private static bool IsFrameworkRegistered(ProcessorArchitecture systemArchitecture,
    PackageVersion minVersion)
{
    // Check x86.
    if (!IsPackageRegisteredForCurrentUser(
        global::Microsoft.WindowsAppSDK.Runtime.Packages.Framework.PackageFamilyName,
        minVersion, ProcessorArchitecture.X86,
        PackageTypes.Framework))
    {
        return false;
    }

    // Check x64 (if necessary).
    if ((systemArchitecture == ProcessorArchitecture.X64) || 
        (systemArchitecture == ProcessorArchitcture.Arm64))
    {
        if (!IsPackageRegisteredForCurrentUser(
            global::Microsoft.WindowsAppSDK.Runtime.Packages.Framework.PackageFamilyName,
            minVersion, ProcessorArchitecture.X64,
            PackageTypes.Framework))
        {
            return false;
        }
    }

    // Check arm64 (if necessary).
    if (systemArchitecture == ProcessorArchitcture.Arm64)
    {
        if (!IsPackageRegisteredForCurrentUser(
            global::Microsoft.WindowsAppSDK.Runtime.Packages.Framework.PackageFamilyName,
            minVersion, ProcessorArchitecture.Arm64,
            PackageTypes.Framework))
        {
            return false;
        }
    }

    return true;
}

private static bool IsMainRegistered(ProcessorArchitecture systemArchitecture,
    PackageVersion minVersion)
{
    return IsPackageRegisteredForCurrentUser(
        global::Microsoft.WindowsAppSDK.Runtime.Packages.Main.PackageFamilyName,
        minVersion,
        systemArchitecture,
        PackageTypes.Main);
}

private static bool IsSingletonRegistered(ProcessorArchitecture systemArchitecture,
    PackageVersion minVersion)
{
    return IsPackageRegisteredForCurrentUser(
        global::Microsoft.WindowsAppSDK.Runtime.Packages.Singleton.PackageFamilyName,
        minVersion,
        systemArchitecture,
        PackageTypes.Main);
}

private static bool IsDDLMRegistered(ProcessorArchitecture systemArchitecture,
    PackageVersion minVersion)
{
    // ...similar to IsFrameworkRegistered, but the packageFamilyName is more complicated...
    // ...and no predefined constant is currently available...
    // ...for more details, see
    // https://github.com/microsoft/WindowsAppSDK/blob/main/specs/Deployment/MSIXPackages.md.
}

上記の情報とコードでは、基本的な検出シナリオについて説明します。 ランタイムがすべてのユーザーに対してプロビジョニングされているかどうかを検出したり、アプリ コンテナーから上記を実行したり、パッケージ化された mediumIL プロセスから実行したりするには、追加のロジックが必要です。

デプロイメント シナリオ

  • Windows App SDK ランタイムをシステム全体にインストールする: システム全体のインストールでは、将来追加される新しいユーザーを含むすべてのユーザーのコンピューターが変更されます。 アプリが管理者特権で実行されていて、インストールを行うユーザーが管理者特権を持っている場合、インストーラーは ProvisionPackageForAllUsersAsync を呼び出して MSIX パッケージをシステム全体で登録します。 システム全体にわたる登録が成功しない場合は、インストールを実行している現在のユーザーに対してのみインストールが実行されます。 管理されているエンタープライズ環境では、IT 管理者が、通常どおりにすべてのユーザーに対してプロビジョニングできる必要があります。

  • Windows アプリ SDK インストーラーによって再配布されるアーキテクチャ: Windows アプリ SDK インストーラーは、x86x64、およびArm64アーキテクチャで使用できます。 インストーラーの各バージョンには、名前が付けられた特定のアーキテクチャ専用の MSIX パッケージが含まれています。 たとえば、x64 デバイスまたは Arm64 デバイスで x86 WindowsAppRuntimeInstall.exe を実行した場合、その x86 インストーラーはそのデバイスに x86 アーキテクチャのパッケージにのみ展開されます。

  • すべての Windows App SDK MSIX パッケージが既にコンピューターにインストールされている: MSIX パッケージがシステム全体にわたる場所にインストールされており、ディスク上には 1 つのコピーのみが存在します。 MSIX パッケージのすべての依存関係が既にマシンにインストールされているときにアプリが Windows App SDK のインストールを試行した場合、そのインストールは実行されません。

  • 1 つ以上の Windows App SDK MSIX パッケージがコンピューターにインストールされていない: Windows App SDK をデプロイする場合は、すべての依存関係が確実にインストールされるようにして、エンドユーザー エクスペリエンスの中断を回避するために、常にすべての MSIX パッケージ (フレームワーク、メイン、シングルトン、DDLM) のインストールを試みます。

外部の場所でパッケージ化されたアプリまたはパッケージ化されていないアプリのランタイム要件

外部の場所でパッケージ化されたアプリ、またはパッケージ化されていないアプリには、Windows App SDK ランタイムを使用するための追加のランタイム要件があります。 これには、実行時に Windows App SDK Framework パッケージを参照して初期化することが含まれます。 さらに、動的依存関係 API を使用して、Windows App SDK の外部にある他のフレームワーク パッケージを参照できます。

Windows App SDK ランタイムを使用する

外部の場所でパッケージ化されたアプリとパッケージ化されていないアプリでは、実行時に Windows App SDK を使用するためにブートストラップ API を呼び出す必要があります。 これは、アプリで WinUI、アプリ ライフサイクル、MRT Core、DWriteCore などの Windows App SDK 機能を使用する前に必要です。 ブートストラップ コンポーネントを使用すると、外部の場所でパッケージ化されたアプリとパッケージ化されていないアプリで、次の重要なタスクを実行できます。

  • Windows App SDK フレームワーク パッケージを見つけ、アプリのパッケージ グラフに読み込む。
  • Windows App SDK フレームワーク パッケージ用に動的依存関係有効期間マネージャー (DDLM) を初期化する。 DDLM の目的は、Windows App SDK フレームワーク パッケージが外部の場所でパッケージ化されたアプリまたはパッケージ化されていないアプリで使用されている間に、そのパッケージがサービスされないようにすることです。

外部の場所とパッケージ化されていないアプリの Windows アプリ SDK ランタイムを読み込む最も簡単な方法は、プロジェクト ファイル (.csproj または .vcxproj) で <WindowsPackageType>None</WindowsPackageType> プロパティを設定することです。 また、アプリのスタートアップ コードでブートストラップ API を直接呼び出して、初期化をより詳細に制御することもできます。 詳細については、「外部の場所またはパッケージ化されていないアプリで Windows App SDK ランタイムを使用する」および「チュートリアル: Windows App SDK を使用する外部の場所でパッケージ化されたアプリまたはパッケージ化されていないアプリでブートストラップ API を使用する」を参照してください。

動的依存関係のサポートにより、外部の場所でパッケージ化されたアプリとパッケージ化されていないアプリは、MSI や任意のインストーラーなどの既存のデプロイ メカニズムを保持し、アプリケーションでWindows App SDKを活用できます。 動的依存関係は、パッケージ化されたアプリ、外部の場所でパッケージ化されたアプリ、およびパッケージ化されていないアプリで使用できます。ただし、主に外部の場所とパッケージ化されたアプリとパッケージ化されていないアプリで使用することを目的としています。

Windows App SDK フレームワーク パッケージのバージョンとアーキテクチャごとに 1 つの DDLM があります。 つまり、x64 コンピューターでは、x86x64 の両方のアーキテクチャのアプリをサポートするために、その両方のバージョンの DDLM を使用できます。

動的依存関係 API を使用した他のフレームワーク パッケージの参照

Windows App SDK 以外の他のフレームワーク パッケージ (DirectX など) の機能を使用する場合は、外部の場所でパッケージ化されたアプリとパッケージ化されていないアプリで動的依存関係 API を呼び出すことができます。 ブートストラップ コンポーネントに加えて、Windows App SDK には、動的依存関係 API を実装する幅広い C/C++ 関数と WinRT クラスのセットも用意されています。 この API は、実行時に任意のフレームワーク パッケージを動的に参照するために使用されるように設計されています。

詳細については、「デスクトップ アプリから MSIX フレームワーク パッケージを動的に使用する」および「動的依存関係のサンプル」を参照してください

ターゲット コンピューターに .winmd ファイルを展開する

アプリと共に、Windows メタデータ (.winmd) ファイルをデプロイすることをお勧めします。 メタデータは、実行時にさまざまな API や動作で使用でき、メタデータがないと機能が制限されたり、機能しなくなったりする可能性があります。 たとえば、メタデータを使用して、アパートメントの境界を越えてオブジェクトをマーシャリングできます。また、マーシャリングの必要性は、機械の性能の関数である可能性があります。 メタデータが必要かどうかを知る決定論的な方法はないため、サイズを極端に気にしない限り、.winmds をデプロイする必要があります。