カスタム インストール操作
多くのゲームでは、不正行為対策やその他のミドルウェアが使用されています。 これらのコンポーネントは通常、ユーザーがゲームをインストールするときにチェーンインストールされます。 ユーザーは Microsoft Store 経由で 1 つのゲームをインストールし、他の配布チャネルを通じて別のゲームをインストールできます。 プラットフォームでは、両方のゲームが同じミドルウェア パッケージをチェーンインストールした場合に競合が発生しないようにします。 ゲームでは、任意の .exe ファイルや .msi ファイルをパッケージに 1 つ以上含め、アプリのインストール時にそれらのファイルを実行するよう要求できます。 カスタム インストール操作は、不正行為対策ソフトウェアやその他の再頒布可能ミドルウェアをインストールするための機能です。 これにより、Microsoft Store に提出する MSIX に、その他の配布チャネルを通じて提出する .msi ファイルや .exe ファイルとまったく同じチェーンインストーラーの .exe ファイルを使用できるようになります。
従来の Win32 アプリでは、共有のミドルウェアは一般的に個別の再頒布可能ファイル経由でインストールされるため、通常はゲーム自体にバンドルできる自己解凍 .exe や .msi という形を取ります。 Microsoft Store アプリでは、依存コンポーネントはゲームにバンドルされるのではなく、Microsoft Store を経由して個別に展開されるフレームワーク パッケージとしてモデル化されます。 このモデルでは、消費側のアプリ マニフェストで、1 つ以上のフレームワーク パッケージに対する依存関係が宣言されます。 その後、Microsoft Store によって依存コンポーネントのインストールのチェーニングが処理されます。 多くの再頒布可能ファイルは Microsoft Store からフレームワーク パッケージとして利用できますが、一部の再頒布可能ファイルについては、フレームワーク パッケージとして利用できない場合があります。 そのようなパッケージについては、再頒布可能ファイルをゲーム パッケージ内にバンドルできるようにすることで対応します。
.exe や .msi の再頒布可能ファイルを含めるには、MicrosoftGame.config ファイルを更新する必要があります。 これらの変更により、使用するカスタム インストール操作の種類と、インストール パッケージ内での位置を宣言することができます。
再頒布可能ファイルはパッケージ内に含め、MicrosoftGame.config 内で宣言する必要があります。この宣言には、実行可能ファイルへのパスが含まれます (宣言されたフォルダー パスへの相対パスとして指定するため、パッケージ自体のルート パスへの相対パスとなります)。 また、宣言には、実行時に実行可能ファイルに渡されるコマンド ライン引数も含まれています。 これを行うには、MicrosoftGame.config ファイルに CustomInstallActions 要素を含めます。
CustomInstallActions
CustomInstallActions 要素には、どのようなカスタム インストール操作が実行されるのかや、それらがいつ実行されるのかについてのすべての定義が含まれます。 この拡張機能のインスタンスは、マニフェスト内に 1 つだけ宣言することができます。 この拡張機能には、CustomInstall という最上位の子要素が 1 つ存在します。 これには Folder という必須の属性が 1 つあります。これは、すべてのカスタム操作に必要なすべてのファイルが含まれているフォルダーを指定する文字列です。 このフォルダーには、サブフォルダーを含めることもできます。 デベロッパーは、カスタム操作の実行可能ファイルの依存コンポーネントがパッケージ内に含まれていることと、それらがそれぞれの適切な読み込みパスにあることを確認する必要があります。
注意
主要なゲームの実行可能ファイルやその他のファイルは、指定されたフォルダー内に置かないようにしてください。 これは、カスタム インストール ファイル専用です。
アプリでは、カスタム インストール拡張機能内で、InstallAction、RepairAction、UninstallAction の各子要素を宣言することができます。 これらはすべてオプションです。すべて宣言しても、一切宣言しなくてもかまいません。 これらの各要素内では、子項目として 1 つ以上の InstallAction、RepairAction または UninstallAction を指定します。 プラットフォームでは、指定されたコマンド ライン引数を使用して、指定された操作が指定された順序で実行されます。
操作の種類
カスタム インストール拡張機能の 3 つの子ノードは、特定のカスタム操作がいつ実行されるのかを指示します。 カスタム インストール操作には次の 3 つの種類があります。
- インストール操作: アプリの初回実行の前にプラットフォームで実行される操作
- 修復操作: ユーザーが "修復" または "リセット" を選択したときに実行される操作
- アンインストール操作: ユーザーがアプリをアンインストールするときに実行される操作
通常は、再頒布可能ファイルを InstallAction としてチェーンインストールするように指定し、その後、それを UninstallAction としてアンインストールするように指定します。 ただし、場合によっては、アンインストールを対応付けることなくインストールすることもできます。 その場合、アプリでインストールされたコンポーネントは、アンインストールされた後も保持されます。この方法は、他のアプリと共有される再頒布可能ファイルに適しています。 同様に、RepairAction を使用して、InstallAction 用に指定された実行可能ファイルを再宣言することもできます (こちらが一般的な方法です)。 インストール/修復/アンインストールで実行する各操作では、それぞれ異なる実行可能ファイルが必要になる可能性もあります。 スキーマは非常に柔軟です。プラットフォームでは、そのいずれの操作も必要としません。 ゲームごとに適切な動作を構成できます。
Important
アンインストールの操作は、インストールまたは修復操作が実行されている場合にのみ実行されます。 システムでは、この状態を追跡するために Name プロパティが使用されます。 このため、インストール、修復、アンインストール アクションは同じ名前にすることが重要です。
操作の要素
ファイル
操作ごとに、実行するファイルを指定する必要があります。また、このファイルはパッケージ内に含める必要があります。 パスを指定した場合、そのパスは、CustomInstallActionsフォルダパスに対する暗黙的な相対パスになります。 絶対パスを指定することはできません。 パスの先頭に "\\" 文字を使用することはできません。
名前
操作には名前を指定する必要があります。 この名前は、親の Actions ノード内で一意である必要がありますが、異なる Actions ノード間で共有することもできます。 たとえば、ファイルを "MySetup.exe" と指定し、InstallAction と RepairAction の両方の名前を "abc123" と指定することもできます。 ただし、InstallAction 要素が 2 つある場合は、それぞれに異なる名前を指定する必要があります。 同じ実行可能ファイルに対しては、その実行可能ファイルが変更されない限り、パッケージ バージョン間で同じ名前を使用する必要があります。 名前は操作の ID として使用されます。これによりプラットフォームは、どの操作が正常に実行されたかや、更新されたパッケージに対してそれらを実行する必要があるかどうかを追跡できるようになります。 更新されたパッケージで、既に正常に実行された名前のカスタム アクションが指定されている場合、プラットフォームは更新時にその操作をスキップします。
Important
引数リストの違いは、ID の違いを構成するものではありません。 更新されたパッケージで、異なる引数を使用して同じ実行可能ファイルを実行する必要がある場合は、別の名前を指定する必要があります。 デベロッパーは、自身の責任において、宣言された名前を適切に構成し、それらをバージョン間で追跡する必要があります。
引数
各カスタム インストール操作では、3 つ目の要素として、引数が使用されます。これにより、再頒布可能コマンドを実行するために必要な引数を指定することができます。
カスタム操作の使用
通常、不正行為対策ソフトウェアをインストールするには管理者特権が必要です。また一般的に、カスタム操作は非常に強力な機能であるため、カスタム操作が含まれるパッケージについてはプラットフォームで管理者特権が要求されます。 管理者特権で実行される操作の場合、Windows では、アプリの初回実行時にユーザー アカウント制御 (UAC) のプロンプトを表示する必要があります。 ユーザー ワークフローは次のようになります。
- ゲームの Microsoft Store ページには、要件の説明が表示されます。具体的には、インストールに管理者特権が必要かどうかや、インストール時にカスタム操作が実行されるかどうか、またそれがユーザーにとって何を意味するかなどが示されます。 これらの情報は、ユーザーがゲームの購入を適切な情報に基づいて判断できるようにする目的で提供されます。
- ユーザーは、制約や影響について確認したうえで、[インストール] を選択します。
- プラットフォームは、パッケージにカスタム操作が含まれていることを検知し、カスタム操作を実行する必要があるという事実を記録します。 ただし、最初のインストール フェーズ中には、カスタム操作は実行されません。 代わりに、カスタム操作はユーザーが最初にゲームを起動したときに実行されます。
- ゲームの初回起動時には、プラットフォームがカスタム操作を実行しようとする際に、UAC プロンプトが表示されます。 その後、ユーザーは管理者の資格情報を入力し、昇格に同意する必要があります。 パッケージに複数のカスタム操作が含まれている場合でも、ユーザーに表示される UAC プロンプトは 1 つだけです。 1 つ以上のカスタム操作が変更されない限り、それ以上の UAC プロンプトが更新のために表示されることはありません。 ゲームがアンインストールされるときに、UAC プロンプトが表示されます。
すべてのカスタム操作は、成功した場合に 0 を返す必要があります。 いずれかのカスタム操作が失敗した場合、プラットフォームは残りのカスタム操作の実行を継続して、引き続きアプリを起動しようとします。 後続のアプリが起動するたびに、プラットフォームは失敗した (または完了していない) インストール カスタム操作を再試行し、操作が成功するまで継続します。 カスタム操作のエラーによってアプリが正常に機能しない場合、ユーザーはいつでもアプリの設定ページに移動して、修復またはリセットを選択することができます。 修復やリセットでは、ゲーム ファイルは再ダウンロードされません。単にパッケージが再登録されます。 失敗したまたは実行されなかったカスタム アクションは、再登録されて実行されます。 成功した場合に 0 以外の値を返すカスタム インストーラーがある場合は、1 つの方法として、成功時にゼロを返す別の実行可能ファイルを作成し、その中に当該のインストーラーをラップするという方法もあります。
Microsoft Store ポリシーには、チェーンインストールできるミドルウェア/再頒布可能ソフトウェアの種類に関するガイドラインが含まれています。 大まかに言うと、チェーン インストールは、ゲームの実行に必要な共有のソフトウェアをインストールするための機能です。 関連のないアプリや他のソフトウェアをインストールするための機能ではありません。
注意
カスタム インストール操作は、メインの MSIXVC パッケージ内でのみサポートされます。 フレームワーク パッケージ、オプションのパッケージ、変更パッケージ、およびその他の種類のパッケージではサポートされません。
MSI をカスタム インストール操作として実行する
MSI の場合は、MSI の名前を指定すると、プラットフォームがそのファイルに対して msiexec.exe を実行します。 引数として、/i、/f、/x は指定しないでください。これらは、宣言された操作の種類 (インストール、修復またはアンインストール) から推測されるためです。 /f スイッチに対してオプションを指定することはできません。 ただし、msiexec.exe に対して通常指定されるその他のオプションの引数は指定できます。 これは、コマンドライン引数が制限される唯一のシナリオです。MSI 以外の操作については、必要な引数を自由に指定できます。 MSI 以外の操作の場合、プラットフォームは引数を解析も検証もしません。 プラットフォームは、単に実行可能ファイルにそれらを渡します。 したがって、デベロッパーは引数が正しいことを自身の責任で確認する必要があります。
MST (MSI 変換) に対する直接のサポートはありません。 MSI/MST を使用する必要がある場合は、1 つの対処法として、MSI を実行するために msiexec をラップする個別の .exe を作成し、MST を適用するという方法もあります。
ゲーム構成ファイルの変更
次の XML サンプルは、MicrosoftGame.config ファイルの内容を適切に追加して、カスタム インストール操作を実行する方法を示したものです。
<!-- Include CustomInstallActions element. Declare InstallActions,
RepairActions and/or UninstallActions as appropriate for your app. -->
<DesktopRegistration>
<!-- ... -->
<!-- Other entries omitted for brevity. -->
<!-- ... -->
<CustomInstallActions>
<Folder>MyInstallers</Folder>
<InstallActionList>
<InstallAction File="CustomInstaller.exe" Name="TaskName" Arguments="/silent /example" />
</InstallActionList>
<RepairActionList>
<RepairAction File="CustomInstaller.exe" Name="TaskName" Arguments="/silent /repair" />
</RepairActionList>
<UninstallActionList>
<UninstallAction File="CustomInstaller.exe" Name="TaskName" Arguments="/silent /remove" />
</UninstallActionList>
</CustomInstallActions>
</DesktopRegistration>
上記の例では、すべての実行可能ファイルとその依存コンポーネントを、パッケージのルートに指定した MyInstallers フォルダーに配置する必要があります。 そのフォルダー内に、アプリに適した任意のサブフォルダー構造を作成できます。 この例では、MySetup.exe へのパスは、<package root>\MyInstallers\Banana\MySetup.exe になります。 この実行可能ファイルに依存コンポーネントがある場合は、それらも適切なフォルダーやサブフォルダーに配置する必要があります。
次のシーケンスは、複数のバージョンを対象にしたマニフェストの作成方法を示したものです。
<!-- v1 of the game. -->
<CustomInstallActions>
<Folder>MyInstallers</Folder>
<InstallActionList>
<InstallAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /example" />
<!-- The platform records the successful install of TaskName_1. -->
</InstallActionList>
<RepairActionList>
<RepairAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /repair" />
</RepairActionList>
<UninstallActionList>
<UninstallAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /remove" />
<!-- The platform records the successful uninstall of TaskName_1. -->
</UninstallActionList>
</CustomInstallActions>
<!-- v2 of the game, where the redist is NOT updated. -->
<CustomInstallActions>
<Folder>MyInstallers</Folder>
<InstallActionList>
<InstallAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /example" />
<!-- The platform detects that we've already installed TaskName_1, so we don't
run it again. Therefore, there's no UAC prompt. -->
</InstallActionList>
<RepairActionList>
<RepairAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /repair" />
</RepairActionList>
<UninstallActionList>
<UninstallAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /remove" />
</UninstallActionList>
</CustomInstallActions>
<!-- v2 of the game, where a redist IS updated. -->
<CustomInstallActions>
<Folder>MyInstallers</Folder>
<InstallActionList>
<InstallAction File="CustomInstaller.exe" Name="TaskName_2" Arguments="/silent /example" />
<!-- The platform detects that we haven't previously run TaskName_2, so we need
to run it this time and show a UAC prompt. -->
</InstallActionList>
<RepairActionList>
<RepairAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /repair" />
</RepairActionList>
<UninstallActionList>
<UninstallAction File="CustomInstaller.exe" Name="TaskName_1" Arguments="/silent /remove" />
</UninstallActionList>
</CustomInstallActions>