Windows でパッケージ化されたデスクトップ アプリが動作するしくみについて

このトピックでは、Windows アプリ パッケージを作成できるデスクトップ アプリケーションの種類と、注意が必要なオペレーティング システム (OS) の動作およびその他の詳細について説明します。 次の項目について、詳細を説明します (ご覧のとおり、特定の動作はアプリの種類によって異なります)。

デスクトップ アプリケーションの種類

作成してパッケージ化できるデスクトップ アプリケーションには、2 種類あります。 Application 要素の uap10:RuntimeBehavior 属性を使用して、アプリ パッケージ マニフェストでアプリの種類を宣言します。

  • これらの種類のうちの 1 つには、WinUI 3 アプリ (Windows アプリ SDK を使用) とデスクトップ ブリッジ アプリ (Centennial) の両方が含まれます。 uap10:RuntimeBehavior="packagedClassicApp" で宣言されます。
  • もう 1 つは、外部の場所でパッケージ化されたアプリを含む、他の種類の Win32 アプリを表します。 uap10:RuntimeBehavior="win32App" で宣言されます。

ユニバーサル Windows プラットフォーム (UWP) アプリ (uap10:RuntimeBehavior="windowsApp") もパッケージ化されていますが、このトピックでは扱いません。

その後、(同じ Application 要素の) uap10:TrustLevel 属性により、パッケージ アプリのプロセスがアプリ コンテナー内で実行されるかどうかが決定されます。

  • 完全な信頼アプリ。 uap10:TrustLevel="mediumIL" で宣言されます。
  • appContainer アプリ。 uap10:TrustLevel="appContainer" で宣言されます。 軽量のアプリ コンテナー内で実行されます (そのため、ファイル システムとレジストリ仮想化を使用して分離されています)。 詳細については、「MSIX appContainer アプリ」を参照してください。

重要

詳細、依存関係、機能の要件については「アプリケーション」でこれら 2 つの属性についてのドキュメントを参照してください。 また、「uap10 は、Windows 10 バージョン 2004 (10.0;ビルド 19041)」も参照してください。

パッケージ化の目的とアプリ コンテナー

アプリをパッケージ化する目的は、実行時にパッケージ ID を付与するためです。 特定の Windows 機能にはパッケージ ID が必要です (「パッケージ ID が必要な機能」を参照)。 上記で説明したアプリの種類のすべての組み合わせをパッケージ化できます (これにより、パッケージ ID のメリットを受けることができます)。

しかし appContainer アプリの主な目的は、他のアプリとの互換性を維持しつつ、アプリの状態をシステムの状態からできるだけ分離することです。 Windows では、実行時にファイル システムとレジストリに加える特定の変更を検出してリダイレクトすることで実現します (仮想化と呼ばれます)。 仮想化されたアプリにのみセクションが適用される場合は、このセクションを呼び出します。

インストール

アプリ パッケージは、システム全体ではなくユーザーごとにインストールされます。 新しいマシン上の新しいパッケージの既定の場所は、C:\Program Files\WindowsApps\<package_full_name> にあります。これには、app_name.exe という名前の実行可能ファイルが含まれます。 ただし、パッケージは他の場所にインストールできます。たとえば、Visual Studio の Start コマンドではプロジェクトの $(OutDir) が使用されます。

展開後、パッケージ ファイルは読み取り専用としてマークされ、オペレーティング システム (OS) によって厳重にロックダウンされます。 それらのファイルが改ざんされると、Windows によりアプリの起動が回避されます。

C:\Program Files\WindowsApps の場所は、PackageVolume と呼ばれます。 この場所は Windows が付属している既定の PackageVolume ですが、任意のドライブと任意のパスに PackageVolume を作成できます。 また、すべてのパッケージが PackageVolume にインストールされるわけではありません (上記の Visual Studio の例を参照してください)。

ファイル システム

OS では、フォルダーの場所に応じて、パッケージ化されたデスクトップ アプリに対するさまざまなレベルのファイル システム操作がサポートされています。

デバイスに応じた最適化

ファイルの重複を避ける (これによりディスク記憶領域を最適化し、ファイルをダウンロードする際に必要な帯域幅を削減する) ため、OS では、単一の記憶域とファイルのハード リンクが利用されます。 ユーザーが MSIX パッケージをダウンロードする際、AppxManifest.xml を使用して、パッケージに含まれているデータが以前のパッケージのインストールによってディスク上に既に存在するかどうかが確認されます。 同じファイルが複数の MSIX パッケージ内に存在する場合は、その後 OS によって共有ファイルがディスク上に 1 回だけ保存され、両方のパッケージから共有ファイルへのハード リンクが作成されます。 ファイルは 64 Kb のブロックでダウンロードされるため、ダウンロードされるファイルの一部分がディスク上に存在する場合でも、異なる増分のみがダウンロードされます。 これにより、ダウンロードに使用される帯域幅を削減できます。

Windows 10 バージョン 1903 以降の AppData 操作

このセクションは仮想化されたアプリにのみ適用されます。

ユーザーの AppData フォルダー (例: C:\Users\<user_name>\AppData) に新しく作成されたすべてのファイルとフォルダーは、ユーザーごと、アプリごとのプライベートな場所に書き込まれますが、実行時にマージされ実際の AppData の場所に表示されます。 これにより、アプリ自体によってのみ使用される成果物に対して、ある程度の状態の分離が可能になり、アプリのアンインストール時に、システムでそれらのファイルをクリーンアップできるようになります。

ユーザーの AppData フォルダーにある既存のファイルに変更を加えることによって、アプリと OS の間でより高いレベルの互換性と対話機能を提供できるようになります。 これにより、アプリによって行われるすべてのファイルまたはディレクトリの変更が OS に認識されるため、システムの "劣化" が抑えられます。 また、状態を分離することで、パッケージ化したデスクトップ アプリケーションでは、同じアプリのパッケージ化されていないバージョンが停止した場所から開始することもできます。 仮想ファイル システム (VFS) フォルダーは、ユーザーの AppData フォルダーとして OS でサポートされていないことにご注意ください。

Windows 10 バージョン 1903 以前の OS での AppData 操作

このセクションは仮想化されたアプリにのみ適用されます。

作成、削除、更新など、ユーザーの AppData フォルダー (例: C:\Users\<user_name>\AppData) に対する書き込みはすべて、書き込み時にユーザーごと、アプリごとのプライベートな場所にコピーされます。 これにより、パッケージ アプリによって、実際にはプライベート コピーを変更しているときに実際の AppData を編集しているような錯覚が生まれます。 このように書き込みのリダイレクトを行うことで、アプリによって行われたすべてのファイル変更をシステムで追跡できます。 これにより、アプリのアンインストール時にシステムがそれらのファイルをクリーンアップできるため、システムの "劣化" を抑え、ユーザーから見たアプリ削除の操作を改善することができます。

作業ディレクトリとアプリケーション ファイル

このセクションは仮想化されたアプリにのみ適用されます。

AppData のリダイレクトに加えて、Windows の既知のフォルダー (System32Program Files (x86) など) がアプリ パッケージ内の対応するディレクトリに動的にマージされます。 それぞれのパッケージのルートには、VFS という名前のフォルダーが含まれています。 VFS ディレクトリ内のディレクトリまたはファイルの読み取りはすべて、実行時に対応するネイティブ部分にマージされます。 たとえば、アプリがアプリ パッケージの一部として C:\Program Files\WindowsApps\<package_full_name>\VFS\SystemX86\vc10.dll を含んでいる場合、ファイルは C:\Windows\System32\vc10.dll にインストールされているように表示されます。 これにより、ファイルがパッケージ外の場所にあることを想定しているデスクトップ アプリケーションとの互換性が維持されます。

アプリ パッケージ内のファイルまたはフォルダーへの書き込みは、許可されていません。 パッケージに含まれないファイルやフォルダーへの書き込みは、OS では無視され、ユーザーにアクセス許可があれば許可されます。

一般的なファイル システムの操作

一般的なファイル システム操作と OS での処理方法を以下の表に示します。

操作 結果
既知の Windows ファイルまたはフォルダーの読み取りまたは列挙 C:\Program Files\<package_full_name>\VFS\<well_known_folder> がローカル システムの対応部分に動的にマージされます。 C:\Windows\System32 の読み取りでは、C:\Windows\System32 の内容と C:\Program Files\WindowsApps\<package_full_name>\VFS\SystemX86 の内容が返されます。
AppData への書き込み Windows 10 バージョン 1903 以降: 次のディレクトリの下に作成された新しいファイルとフォルダーは、ユーザーごと、パッケージごとのプライベートな場所にリダイレクトされます。
  • ローカル
  • Local\Microsoft
  • ローミング
  • Roaming\Microsoft
  • Roaming\Microsoft\Windows\Start Menu\Programs
ファイルを開くコマンドに応答して、OS によってユーザーごと、パッケージごとの場所から最初にファイルが開かれます。 この場所が存在しない場合、OS は実際の AppData の場所からファイルを開こうと試みます。 ファイルが実際の AppData の場所から開かれた場合、そのファイルの仮想化は実行されません。 ユーザーにアクセス許可がある場合は、AppData でのファイルの削除が許可されます。

Windows 10 Version 1903 およびそれ以前: 書き込み時に、ユーザーごと、アプリごとの場所にコピーされます。

AppData は通常、C:\Users\<user_name>\AppData です。
パッケージ内への書き込み 許可されていません。 パッケージは読み取り専用です。 C:\Program Files\WindowsApps\<package_full_name> への書き込みは、許可されていません。
パッケージ外への書き込み ユーザーにアクセス許可がある場合、許可されます。 C:\Windows\System32\foo.dll への書き込みは、パッケージに C:\Program Files\WindowsApps\<package_full_name>\VFS\SystemX86\foo.dll が含まれておらずユーザーにアクセス許可がある場合、許可されます。

パッケージ化された VFS の場所

このセクションは仮想化されたアプリにのみ適用されます。

次の表は、パッケージの一部として含まれるファイルが、システム上でアプリのために配置される場所を示しています。 これらのファイルは、アプリでは示されているシステム内の場所にあると認識されますが、実際にはリダイレクトされており、C:\Program Files\WindowsApps\<package_full_name>\VFS 内の場所に配置されます。 FOLDERID の場所は KNOWNFOLDERID 定数で示されます。

システムの場所 リダイレクトされた場所 ([<package_root>]\VFS の下) アーキテクチャで有効
FOLDERID_SystemX86 SystemX86 x86、amd64
FOLDERID_System SystemX64 amd64
FOLDERID_ProgramFilesX86 ProgramFilesX86 x86、amd6
FOLDERID_ProgramFilesX64 ProgramFilesX64 amd64
FOLDERID_ProgramFilesCommonX86 ProgramFilesCommonX86 x86、amd64
FOLDERID_ProgramFilesCommonX64 ProgramFilesCommonX64 amd64
FOLDERID_Windows Windows x86、amd64
FOLDERID_ProgramData 一般的な AppData x86、amd64
FOLDERID_System\catroot AppVSystem32Catroot x86、amd64
FOLDERID_System\catroot2 AppVSystem32Catroot2 x86、amd64
FOLDERID_System\drivers\etc AppVSystem32DriversEtc x86、amd64
FOLDERID_System\driverstore AppVSystem32Driverstore x86、amd64
FOLDERID_System\logfiles AppVSystem32Logfiles x86、amd64
FOLDERID_System\spool AppVSystem32Spool x86、amd64

レジストリ

このセクション (およびサブセクション) は、仮想化されたアプリにのみ適用されます。

アプリ パッケージには、実際のレジストリ内の HKLM\Software と論理的に (事実上) 同等なものとして機能する、registry.dat ファイルが含まれています。 実行時、仮想レジストリでは、このハイブの内容がネイティブ システム ハイブにマージされ、両方が一括で表示されます。 たとえば、registry.dat に単一のキー Foo が含まれている場合、実行時に HKLM\Software を読み取ると、(すべてのネイティブ システム キーに加えて) Foo も含まれているように表示されます。

MSIX パッケージには HKLM および HKCU キーが含まれていますが、扱いはそれぞれ異なります。 パッケージに含まれる部分は HKLM\Software 以下のキーのみです。HKCU 以下のキーまたはレジストリの他の部分は含まれません。 パッケージ内のキーまたは値への書き込みは許可されていません。 パッケージに含まれないキーまたは値への書き込みは、ユーザーにそのアクセス許可があれば許可されます。

HKCU への書き込みはすべて、書き込み時にユーザーごと、アプリごとのプライベートな場所にコピーされます。 従来、アンインストーラーは HKEY_CURRENT_USER をクリーンアップできませんでした。これは、ログアウトしたユーザーのレジストリ データはマウント解除され使用できなくなるためです。

書き込みはすべて、パッケージのアップグレード中には保持され、アプリが完全に削除された場合にのみ削除されます。

一般的なレジストリ操作

このセクションのほとんどは、仮想化されたアプリにのみ適用されます。

一般的なレジストリ操作と OS での処理方法を以下の表に示します。

操作 結果
HKLM\Software の読み取りまたは列挙 パッケージ ハイブがローカル システムの対応部分に動的にマージされます。 registry.dat に単一のキー Foo が含まれている場合、実行時に HKLM\Software を読み取ると、HKLM\SoftwareHKLM\Software\Foo の両方の内容が表示されます。
HKCU への書き込み ユーザーごと、アプリごとのプライベートな場所にコピーされます。 ファイルの AppData と同じです。
パッケージ内への書き込み。 許可されていません。 パッケージは読み取り専用です。 パッケージ ハイブに対応するキー/値が存在する場合、HKLM\Software への書き込みは許可されません。
パッケージ外への書き込み OS では無視されます。 ユーザーにアクセス許可がある場合、許可されます。 HKLM\Software への書き込みは、対応するキー/値がパッケージ ハイブ に存在せず、ユーザーが適切なアクセス許可を持っている場合に許可されます。

アンインストール

このセクションは仮想化されたアプリにのみ適用されます。

パッケージがユーザーによりアンインストールされると、C:\Program Files\WindowsApps\<package_full_name> にあるすべてのファイルとフォルダーは削除されます。また、パッケージ化のプロセス中にキャプチャされた AppData またはレジストリへのリダイレクトされた書き込みもすべて削除されます。