本主題描述您可以為其建立 Windows 應用程式套件的桌面應用程式類型,並且討論到一些作業系統 (OS) 的行為及其他需要注意的重要細節。 我們將深入探討下列專案的詳細數據(如我們所見,特定行為取決於您的應用程式類型):
桌面應用程式類型
您可以建立和封裝兩種類型的傳統型應用程式。 您可以使用 Application 元素的 uap10:RuntimeBehavior 屬性,在其應用程式套件指令清單中宣告 應用程式的 類型:
- 其中一種類型包括使用 Windows App SDK 的 WinUI 3 應用程式和桌面橋接(Centennial)應用程式。 使用
uap10:RuntimeBehavior="packagedClassicApp"
宣告。 - 另一種類型代表其他類型的 Win32 應用程式,包括 以外部位置封裝的應用程式。 使用
uap10:RuntimeBehavior="win32App"
宣告。
通用 Windows 平台(UWP)app(uap10:RuntimeBehavior="windowsApp"
)也已封裝,但本主題不涉及它們。
然後 uap10:TrustLevel 屬性(相同 Application 元素的)會決定封裝應用程式的進程是否在應用程式容器內執行。
-
完全信任的應用程式。 使用
uap10:TrustLevel="mediumIL"
宣告。 -
appContainer 應用程式。 使用
uap10:TrustLevel="appContainer"
宣告。 在輕量型應用程式容器中執行 (因此會使用檔案系統和登錄虛擬化隔離)。 如需詳細資訊,請參閱 MSIX appContainer 應用程式。
這很重要
如需詳細數據、相依性和功能需求,請參閱 應用程式中這兩個屬性的檔。 另請參閱 Windows 10 版本 2004(10.0;組建 19041)中引入的 uap10。
封裝和應用程式容器的目的
封裝應用程式的目的是在運行時間授與其 套件身分識別 。 某些 Windows 功能需要套件身分識別(請參閱 需要套件身分識別的功能)。 您可以封裝上述 應用程式類型的所有 組合(藉此受益於 套件身分識別)。
但 appContainer 應用程式的主要目標是盡可能將應用程式狀態與系統狀態分開,同時維持與其他應用程式的相容性。 Windows 可藉由偵測並重新導向它在運行時間對文件系統和登錄所做的特定變更來達成此目的(稱為 虛擬化)。 當區段僅適用於虛擬化應用程式時,我們將會指出。
安裝
應用程式套件會以每個用戶為基礎安裝,而不是全系統安裝。 新電腦上新套件的預設位置位於 底下 C:\Program Files\WindowsApps\<package_full_name>
,可執行檔名為 app_name.exe。 但套件可以安裝在其他地方;例如,Visual Studio 的 Start 命令會使用專案的 $(OutDir)
。
部署之後,套件檔案會被標示為只讀,並受到作業系統的嚴密鎖定。 如果這些檔案遭到竄改,Windows 會防止應用程式啟動。
位置 C:\Program Files\WindowsApps
是所謂的 PackageVolume。 該位置是 Windows 隨附的預設 PackageVolume;但是您可以在任何磁碟驅動器和任何路徑上建立 PackageVolume。 此外,並非所有套件都安裝在 PackageVolume 中(請參閱上述 Visual Studio 範例)。
檔案系統
OS 支援封裝傳統型應用程式的不同檔案系統作業層級,視資料夾位置而定。
已針對您的裝置優化
為了避免檔案重複(為了優化磁碟空間,並減少下載檔案時所需的頻寬),OS 會利用單一記憶體和檔案的硬式連結。 當使用者下載 MSIX 套件時, AppxManifest.xml
會用來判斷隨附套件的數據是否已經存在於先前套件安裝的磁碟上。 如果相同的檔案存在於多個 MSIX 套件中,則 OS 只會將共用檔案儲存在磁碟上一次,並且從這兩個套件建立共用檔案的硬式連結。 由於檔案會以 64KB 區塊下載,因此即使檔案的部分已存在於磁碟上,也只會下載不同的增量。 這可減少用於下載的頻寬。
Windows 10 版本 1903 和更新版本的 AppData 作業
本節僅適用於虛擬化應用程式。
使用者資料夾中所有新建立的 AppData
檔案和資料夾 (例如, C:\Users\<user_name>\AppData
) 都會寫入專屬於每個使用者和應用程式的私人位置,並在運行期間被合併以顯示在實際的 AppData
位置。 這允許只供應用程式本身使用的成品進行某種程度的狀態區隔;可讓系統在卸載應用程式時清除這些檔案。
允許使用者修改使用者 AppData
資料夾下的現有檔案,以提供應用程式與OS之間的更高程度的相容性和互動性。 這可減少系統「腐爛」,因為 OS 知道應用程式所做的每個檔案或目錄變更。 狀態分離也允許已封裝的桌面應用程式從相同應用程式的未封裝版本中斷的地方繼續運行。 請注意,OS 不支援使用者資料夾的 AppData
虛擬檔案系統 (VFS) 資料夾。
早於 Windows 10 版本 1903 的作業系統上的 AppData 操作
本節僅適用於虛擬化應用程式。
所有對使用者 AppData
資料夾(例如 C:\Users\<user_name>\AppData
)的寫入操作,包括建立、刪除和更新,都是在寫入時被複製到每個使用者和每個應用程式的私人位置。 這會讓人產生錯覺,以為已封裝的應用程式正在編輯真正的 AppData
,而實際上是在修改一個私人複本。 透過重新導向寫入的方式,系統可以追蹤應用程式所做的所有檔案修改。 這可讓系統在卸載應用程式時清除這些檔案,進而減少系統「腐爛」,併為使用者提供更好的應用程式移除體驗。
工作目錄和應用程式檔
本節僅適用於虛擬化應用程式。
除了重新導向 AppData
之外,Windows 的已知資料夾 (System32
、 Program Files (x86)
等等) 也會動態地與應用程式套件中的對應目錄合併。 每個套件都包含位於其根目錄的資料夾 VFS
。 在 VFS
目錄中,對任何目錄或檔案的讀取,會在執行時與其各自的本地對應項合併。 例如,應用程式可以包含 C:\Program Files\WindowsApps\<package_full_name>\VFS\SystemX86\vc10.dll
做為應用程式套件的一部分,但檔案似乎安裝在 C:\Windows\System32\vc10.dll
。 這可維持與傳統型應用程式的相容性,因為這些應用程式預期檔案會儲存在非套件位置。
不允許寫入應用程式套件中的檔案/資料夾。 不屬於套件一部分的檔案和資料夾會被作業系統忽略,但只要使用者有權限,就允許寫入。
一般檔案系統作業
這個簡短的參考數據表會顯示常見的文件系統作業,以及作系統如何處理它們。
行動 | 結果 | 範例 |
---|---|---|
讀取或列舉已知的 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 和更新版本:下列目錄下建立的新檔案和資料夾會重新導向至每個使用者、每個套件的私人位置:
AppData 位置開啟檔案。 如果檔案是從實際 AppData 位置開啟,則不會發生該檔案的虛擬化。 如果使用者具有許可權,則允許刪除AppData 下的檔案。早於 Windows 10 版本 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 |
登記簿
本節(及其子區段)僅適用於虛擬化應用程式。
應用程式套件包含暫時檔案 registry.dat
,其可作為實際登錄中 HKLM\Software 的邏輯(虛擬)等效項目。 在執行時,虛擬註冊表會將該 Hive 的內容合併到原生系統 Hive,以提供兩者的單一檢視。 例如,如果 registry.dat
包含單一密鑰 Foo,則運行時間的 HKLM\Software 讀取也會顯示包含 Foo (除了所有原生系統密鑰外)。
雖然 MSIX 套件包含 HKLM 和 HKCU 金鑰,但會以不同的方式處理它們。 只有 HKLM\Software 下的金鑰是套件的一部分; HKCU 底下的機碼或登錄的其他部分則不是。 不允許寫入封裝中的索引鍵或值。 只要使用者具有許可權,就允許寫入不屬於套件的鍵或值。
HKCU 下的所有寫入在執行時,會複製到每個使用者、每個應用程式的私人位置。 傳統上,卸載程式無法清除 HKEY_CURRENT_USER ,因為註銷使用者的登錄數據已卸除且無法使用。
所有寫入都會在套件升級期間保留,而且只有在完全移除應用程式時才會刪除。
常見的登錄作業
本節大部分僅適用於虛擬化應用程式。
這個簡短的參考數據表會顯示常見的登錄作業,以及作系統如何處理它們。
行動 | 結果 | 範例 |
---|---|---|
讀取或列舉 HKLM\Software | 封裝Hive與本機系統對應專案的動態合併。 | 如果 registry.dat 包含單一密鑰 Foo,則在運行時間讀取 HKLM\Software 會顯示 HKLM\Software 和 HKLM\Software\Foo 的內容。 |
在HKCU下進行寫入 | 寫入時複製到專屬於用戶和應用程式的私人位置。 | 與 AppData 檔案相同。 |
將內容寫入包裝內部。 | 不允許。 套件是唯讀的。 | 如果套件 Hive 中有對應的索引鍵/值存在,則不允許在 HKLM\Software 下寫入。 |
寫入套件外部 | 被作業系統忽略。 如果使用者具有許可權,則允許。 | 只要套件 Hive 中沒有對應的索引鍵/值,而且使用者具有正確的訪問許可權,就會允許在 HKLM\Software 下寫入。 |
解除安裝
本節僅適用於虛擬化應用程式。
當使用者卸載套件時,位於 C:\Program Files\WindowsApps\<package_full_name>
的所有檔案和資料夾,以及在封裝過程中擷取的任何被重新導向至 AppData
的寫入或登錄項目,皆會被移除。