乘風破浪,遇見最美Windows 11之現代Windows桌面應用開發 - 傳統應用通過稀疏包(Sparse Package)插上現代的翅膀


傳統應用通過稀疏包(Sparse Package)插上現代的翅膀

image

許多Windows 10/11可擴展性功能需要在非UWP桌面應用中使用程序包標識符,包括后台任務(BackgroundTasks)通知(Notifications)動態磁貼(LiveTiles)共享目標(Share)。 對於這些情況OS需要使用標識來識別相應API的調用方。

image

在Windows 10版本v2004之前的OS發行版中,向桌面應用授予標識符的唯一方式是將該應用打包到已簽名的MSIX包中。對於這些應用,將在程序包清單中指定標識,並由MSIX部署管道根據清單中的信息處理標識注冊。程序包清單中引用的所有內容都存在於MSIX包中

image

從Windows 10版本v2004開始,可以通過生成稀疏包並將其注冊到應用,向未打包到MSIX包中的桌面應用授予包標識符。通過此支持,尚不能采用MSIX打包方式進行部署的桌面應用可以使用需要程序包標識符的Windows 10/11可擴展性功能

需要包標識的功能(新式Windows 10/11體驗)

https://docs.microsoft.com/zh-cn/windows/apps/desktop/modernize/modernize-packaged-apps

如果要將桌面應用更新為新式Windows 10體驗,請注意,許多功能僅在具有程序包標識符的桌面應用中可用。

可通過多種方式向桌面應用授予程序包標識符:

  • 將其打包到MSIX包中。MSIX是一種新式應用包格式,提供適合所有Windows應用、WPF、Windows窗體和Win32應用的通用打包體驗。它提供了可靠的安裝和更新體驗、功能系統靈活的托管安全模型、對MicrosoftStore的支持、企業管理以及許多自定義分發模型。有關詳細信息,請參閱MSIX文檔中的打包桌面應用程序
  • 如果無法采用MSIX打包來部署桌面應用,那么,自Windows10版本2004起,你可通過創建一個僅包含程序包清單的稀疏MSIX包來授予包標識。有關詳細信息,請參閱向未打包的桌面應用授予標識

如果你的桌面應用具有程序包標識符,可以在其中使用以下功能:

集成包擴展

如果應用程序需要與系統集成(例如,建立防火牆規則),請在應用程序的包清單中描述集成任務,系統將完成其余操作。對於其中的大多數任務,根本不必編寫任何代碼。在清單中添加少量的XML后,可以執行一些操作,例如,在用戶登錄時啟動進程、將應用程序集成到文件資源管理器中,以及為應用程序添加顯示在其他應用中的打印目標列表

有關詳細信息,請參閱將桌面應用與包擴展集成

獲取打包應用的激活信息

從Windows 10 v1809版開始,經過打包的桌面應用可以在啟動過程中檢索某些類型的激活信息。例如,可以獲取通過打開文件、單擊交互式toast或使用協議激活應用的相關信息。

有關詳細信息,請參閱獲取打包應用的激活信息

使用UWP組件進行擴展

某些Windows 10體驗(例如,支持觸摸的UI頁面)必須在新式應用容器內部運行。一般情況下,首先應確定是否可以通過Windows運行時API增強現有桌面應用程序來添加體驗。如果必須使用UWP組件來實現體驗,可將UWP項目添加到解決方案,並使用應用服務在桌面應用程序與UWP組件之間通信

有關詳細信息,請參閱使用UWP組件擴展桌面應用

分發

如果在MSIX包中打包應用,可以通過將應用發布到Microsoft Store或將其旁加載到其他系統來分發應用。

請參閱分發打包的桌面應用

資料和示例

image

未打包的Win32應用程序的身份、注冊和激活

https://blogs.windows.com/windowsdeveloper/2019/10/29/identity-registration-and-activation-of-non-packaged-win32-apps/

許多新的和受歡迎的Windows API和功能,如后台任務(BackgroundTasks)通知(Notifications)動態磁貼(LiveTiles)共享目標(Share) 等,要么無法使用,要么不容易從非打包的Win32應用程序中調用。這是由於UWP APIs的編程模型與系統集成,並對以下概念有依賴性。

  • 身份(Identity) —— 需要包或應用程序的身份來識別調用者,需要一個標識符來確定數據和資源的范圍。
  • 注冊(Registration) —— 在應用部署期間需要配置機器狀態,這是API的要求,並由包或應用身份索引。

對於打包的應用程序,在Appxmanifest.xml中聲明身份,注冊由MSIX部署管道根據AppxManifest.xml中的信息處理。這使得UWP API的調用模式得到簡化,應用程序代碼只需使用一個API。與典型的Win32 API相比,它需要一個注冊-使用-取消注冊的模式來管理一個回調。

我們聽到了你的反饋,作為回應,我們正在填補Win32應用程序和新的Windows API和功能之間的鴻溝,以便你可以利用這些新的API和功能,增強你的應用程序。從Windows Build 10.0.19000.0開始,我們將引入以下新的AppModel概念,為您的Win32應用程序提供與操作系統更深入的整合

  • 稀疏包(Sparse Package)注冊

今天可以在Windows上安裝簽名的MSIX包,但包的Appxmanifest.xml中引用的所有內容必須存在於包內。一個稀疏包包含一個AppxManifest.xml,但與普通/完整包不同,清單可以在預定的 "外部位置(External Location)"引用其包以外的文件。這允許尚未能夠采用完整MSIX打包的應用程序獲得身份,按照UWP API的要求配置狀態(注冊),然后利用這些API的優勢

  • 程序包外部位置(External Location)

為了支持稀疏包,包定義現在有一個新的<allowExternalContent>元素。這就是允許你的包AppxManifest.xml引用其包之外的內容,在磁盤上的一個特定位置。例如,如果你現有的Win32應用程序在C:\Program Files\MyWin32App\中安裝內容,你可以創建一個稀疏包,聲明<allowExternalContent>元素,在應用程序安裝或首次運行時,你可以注冊稀疏包並聲明C:\Program Files\MyWin32App\作為你的應用程序將使用的外部位置(External Location)。這樣你就可以繼續在你現在的位置上部署你所有的其他應用程序工件,同時利用稀疏包的優勢

  • Win32類型的RuntimeBehavior

為了幫助你現有的Win32應用程序在使用稀疏包時的兼容性,應用程序可以注冊以使其應用程序盡可能地像非打包的Win32應用程序一樣運行。這與完全打包的Win32應用程序不同,因為它不受文件系統+注冊表虛擬化、系統的壽命管理和其他完全打包的應用程序的運行時屬性的影響。這種應用程序和完全打包的應用程序之間的主要運行時相似之處是在運行進程中存在"應用程序/包(app/package)"的身份

  • 通過CreateProcess進行激活

今天UWP應用程序的激活路徑確保應用程序在其進程標記中具有"包標識(PackageIdentity)"。這被UWP的API用來識別調用者,並在以后參考——要么執行回調,要么查詢部署期間配置的狀態。由於這個要求,在UWP exe上調用CreateProcess()將會失敗,因為CreateProcess()管道沒有被告知身份。為了支持具有外部位置的稀疏包,我們利用經典的Win32 application.manifest,在CreateProcess()場景中提供身份信息。

這些功能的核心是為未打包的Win32進程提供一個基礎,以使用我們最新的API和功能

請注意,這些仍然是新的、有點高級的開發功能,還沒有完全與Visual Studio集成,即在端到端的編寫經驗中仍然存在一些差距,例如必須在Visual Studio之外創建一個稀疏包

獲取並體驗示例程序PhotoStoreDemo

0. 前言

我們將使用一個使用稀疏包的示例應用程序來了解稀疏包編寫和使用的不同方面。該演示應用程序位於https://aka.ms/sparsepkgsample

我們有一個未打包的WPF應用程序PhotoStoreDemo,用於存儲和顯示照片。在其純粹的未打包狀態下,利用新的Windows APIs和功能可能是一個挑戰。我們的目標是通過創建一個稀疏包並繼續使用我們先前已有的Win32應用程序的工件來改變這種情況

1. 什么是應用程序模型

應用程序模型(App Model) 代表了平台中的核心應用程序激活和生命周期管理基礎設施。這些組件負責實際激活應用程序,創建流程,將應用程序與平台整合,管理激活-暫停-恢復-終止周期,協商資源分配,等等。應用程序模型還暴露了一些以開發者為中心的API,用於診斷。更多信息。

2. Git拉取源碼

git clone https://github.com/microsoft/AppModelSamples.git

image

3. 找到PhotoStoreDemo的解決方案文件

\AppModelSamples\Samples\SparsePackages\WPF+SparsePkg.sln

image

4. 補充安裝.NET Framework 4.6.1

打開WPF+SparsePkg.sln之后,會提示你有項目是通過較老版本的.NET Framework來設計的,所以這里根據提示安裝。

image

裝好之后,就能順利打開項目了。

image

5. 運行並調試PhotoStoreDemo項目

我們在Visual Studio中找到PhotoStoreDemo項目並且把它設置為啟動項目,啟動本地調試就運行起來了。

image

image

稀疏包的剖析

一個稀疏包必須有一個AppxManifest.xml和一組最小的所需的視覺資產,以便部署。

[code lang=”xml”]

<Package
xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
IgnorableNamespaces="uap10">
<Identity Name="PhotoStoreDemo" Publisher="CN=Contoso" … />
<Properties>
…
<Logo>Assets\storelogo.png</Logo>
<uap10:AllowExternalContent>true</uap10:AllowExternalContent>
</Properties>
<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="PhotoStoreDemo"
Executable="PhotoStoreDemo.exe"
uap10:TrustLevel="mediumIL"
uap10:RuntimeBehavior="win32App">
…
</Application>
</Applications>
</Package>

[/code]

讓我們使用上面示例代碼中的AppxManifest.xml來看看稀疏包的結構。

包的外部位置(External Location)

首先,AppxManifest應聲明<AllowExternalContent>包屬性。這允許清單引用不位於包內的內容。稀疏包中引用的任何不直接位於包內的內容都應在"外部"位置,該位置在注冊稀疏包時已指定。

<Properties>
    <DisplayName>PhotoStoreDemo</DisplayName>
    <PublisherDisplayName>Sparse Package</PublisherDisplayName>
    <Logo>Assets\storelogo.png</Logo>
    <uap10:AllowExternalContent>true</uap10:AllowExternalContent>
  </Properties>

image

例如,如果我在安裝期間或第一次運行時聲明我的包的外部位置是C:\Program Files\MyDesktopApp\,為<Logo>屬性定義的圖像storelogo.png應該安裝在C:\Program Files\MyDesktopApp\Assets\storelogo.png,主要應用程序可執行文件PhotoStoreDemo.exe應該安裝在C:\Program Files\MyDesktopApp\PhotoStoreDemo.exe

 <Dependencies>
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18950.0" MaxVersionTested="10.0.19000.0" />
  </Dependencies>

image

此外,MinVersion應該是OS Build 10.0.19000.0(此處存在疑問,是否后續降低了標准?)或更高,Sparse包目前不支持早於這個版本的OS。

值得注意的是,與完全打包的應用程序不同,使用稀疏包+"外部位置(External Location)"的應用程序在部署、運行和卸載時不會被操作系統完全管理。就像現在的Win32應用程序一樣,你的應用程序要負責安裝和卸載它的所有工件,包括稀疏包和"外部位置(External Location)"中的任何內容。這也意味着你的應用程序不能像完全打包的應用程序那樣獲得終身管理和防篡改保護,因為它被安裝在系統上的一個鎖定位置

Win32運行時行為(Win32 Runtime Behavior)

<Application>元素中新引入的TrustLevel=mediumILRuntimeBehavior=Win32App屬性被用來聲明與此稀疏包相關的應用程序將像Win32應用程序一樣運行,沒有注冊表+文件系統虛擬化和其他運行時變化

  <Applications>
    <Application Id="PhotoStoreDemo" Executable="PhotoStoreDemo.exe" uap10:TrustLevel="mediumIL" uap10:RuntimeBehavior="win32App">
      <uap:VisualElements AppListEntry="none" DisplayName="PhotoStoreDemo" Description="PhotoStoreDemo" 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>

image

稀疏包的編寫(Sparse Package Authoring)

編寫稀疏包所需的步驟是。

  1. 創建一個AppxManifest.xml + 視覺資產(Visual Assets)並打包
  2. 簽名稀疏包
  3. 在你的Win32應用程序中創建一個經典的Win32 application.manifest
  4. 注冊稀疏包

創建和打包"AppxManifest.xml"和視覺資產(Visual Assets)

創建應用程序清單

創建一個稀疏包的第一步是生成AppxManifest.xml。AppxManifest需要包含上面列出的屬性,你可以使用這個模板作為一個起點。

我們在項目跟目錄下面創建一個Template文件夾,我們先按下面的模板內容創建一個名為AppxManifest.xml的應用程序清單文件。

<?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="PhotoStoreDemo" ProcessorArchitecture="x86" Publisher="CN=MyPubisher" Version="1.0.0.0" />
  <Properties>
    <DisplayName>Sparse Package Template</DisplayName>
    <PublisherDisplayName>My Publisher</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="MyApp" Executable="MyApp.exe" uap10:TrustLevel="mediumIL" uap10:RuntimeBehavior="win32App">
      <uap:VisualElements DisplayName="MyApp" Description="AppDescription" 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>
    </Application>
  </Applications>
</Package>

image

image

這里面我們可以完善兩個內容,第一個是根據自己的實際情況修改"身份(Identity)"節點的信息,比如應用名稱Name,處理器架構ProcessorArchitecture,發布者信息Publisher,以及程序包版本號Version

根據需要,這里作為示范,稍作修改,改成:

<Identity Name="DemoForSparsePackage" ProcessorArchitecture="x86" Publisher="CN=Contoso Software, O=Contoso Corporation, C=US" Version="1.0.0.0" />

image

緊接着,我們看到"屬性(Properties)"節點的信息,這里面有一個應用顯示名稱DisplayName、發布者顯示名稱PublisherDisplayName,這里也需要進行一些定制修改:

<Properties>
    <DisplayName>SparsePackageDemo</DisplayName>
    <PublisherDisplayName>Contoso Software</PublisherDisplayName>
    <Logo>Assets\StoreLogo.png</Logo>
    <uap10:AllowExternalContent>true</uap10:AllowExternalContent>
</Properties>

另外一個,我們看到"應用(Application)"節點的信息,這里面有個一個應用標識Id和程序文件名Executable,以及程序顯示名稱DisplayName

這里,我們根據需要做一些修改,改成:

<Applications>
    <Application Id="Contoso.DemoForSparsePackage" Executable="DemoForSparsePackage.exe" uap10:TrustLevel="mediumIL" uap10:RuntimeBehavior="win32App">
        <uap:VisualElements DisplayName="DemoForSparsePackage" Description="AppDescription" 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>
    </Application>
</Applications>

同時,這里其實還需要一個真正的DemoForSparsePackage.exe執行文件才行,我們弄一個過來,放在這個目錄下。

image

創建應用視覺資產

除了AppxManifest之外,你還需要包括清單文件中引用的"視覺資產(Visual Assets)"。您可以使用 Visual Studio 應用程序打包項目(Application Packaging Project)package.manifest編輯器中的"視覺資產(Visual Assets)"節點來生成視覺資產。

image

弄好之后,我們在前面的Template文件夾建立一個Assets文件夾,用來存放這些素材。

image

image

通過命令打包

一旦你有了"應用清單文件(AppxManifest.xml)"和"視覺資產(Visual Assets)",你就可以使用"App Packager(MakeAppx.exe)"來創建一個稀疏包。因為稀疏包並不包含AppxManifest.xml中引用的所有文件,你需要指定/nv命令。

下面是一個從VS開發者命令提示符創建只包含AppxManifest.xml的稀疏包的命令示例。

MakeAppx.exe pack /d $AppxManifestFileDir /p $OutputMsixFilePath /nv

你可以在這里找到更多關於"App Packager(MakeAppx.exe)"的信息。

其中在Windows 11中makeappx.exe所在位置:

C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64\makeappx.exe

image

那么我們先切換到它目錄。

cd 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64\'

然后執行命令進行打包:

.\makeappx.exe pack /d 'C:\TempSpace\HelloSparsePackage\Template\' /p 'C:\TempSpace\HelloSparsePackage\Msix\TestPackage.msix' /nv

image

好了,這時候MSIX包就生成了。

image

簽署一個稀疏包

為了在一台機器上成功安裝,你的Sparse包必須用該機器上信任的證書簽名。這就是今天普通MSIX包的情況。你可以為開發目的創建一個新的自簽名證書,並使用Windows SDK和MSIX Toolkit中的SignTool簽署你的稀疏包。你還可以利用新公布的"設備保護簽名(Device Guard Signing)"功能。

下面是一個如何使用"Sign工具(Sign Tool)"從VS開發者命令提示符簽署稀疏包的例子。

SignTool.exe sign /fd SHA256 /a /f <path to cert>\mycert.pfx  /p <cert password>  <Path to Package>\mypackage.msix

為程序包簽名創建證書

https://docs.microsoft.com/zh-cn/windows/msix/package/create-certificate-package-signing

在部署打包的應用之前,Windows對它們進行數字簽名。如果不使用Microsoft Visual Studio創建應用包並簽名,則需要創建和管理自己的代碼簽名證書。可以使用WDK驅動程序工具包中的Pvk2Pfx.exe和Windows創建(證書)。然后,可以使用證書對應用包進行簽名,以便可以部署在本地進行測試。

創建和使用自簽名證書時,只有安裝和信任證書的用戶才能運行應用程序。這很容易用於測試,但可能會阻止其他用戶安裝應用程序。准備好發布應用程序時,建議使用受信任源頒發的證書。這種集中式信任系統有助於確保應用程序生態系統具有驗證級別,以保護用戶免受惡意參與者的攻擊

  1. 確定你的打包應用的主體

若要使用證書給你的應用包簽名,證書中的"主體"必須匹配應用清單中的"發布者"部分

與"應用清單文件(AppxManifest.xml)"的Identity元素的Publisher屬性所填的值要一一對應,等下使用的值必須是Publisher屬性的完整值。

<Identity Name="Contoso.AssetTracker"
    Version="1.0.0.0"
    Publisher="CN=Contoso Software, O=Contoso Corporation, C=US"/>

那么這時候發布者身份就是:CN=Contoso Software, O=Contoso Corporation, C=US 這一整串。

  1. 使用自簽名證書命令創建證書

https://docs.microsoft.com/zh-CN/powershell/module/pki/new-selfsignedcertificate

使用"自簽名證書(New-SelfSignedCertificate)"命令創建證書,它包含一些自定義參數,我們這里側重於創建一個簡單的。

New-SelfSignedCertificate -Type Custom -Subject "CN=Contoso Software, O=Contoso Corporation, C=US" -KeyUsage DigitalSignature -FriendlyName "Your friendly name goes here" -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}")

其中FriendlyName指代我們可以給生成的證書取一個更友好的名字,方便我們記憶,這個就隨意了。

其中KeyUsage指代證書可用於什么,對於自簽名證書,此參數應設置為DigitalSignature,這個參數可選的值包括:

  • CertSign
  • CRLSign
  • DataEncipherment
  • DecipherOnly
  • DigitalSignature
  • EncipherOnly
  • KeyAgreement
  • KeyEncipherment
  • None (default)
  • NonRepudiation

其中TextExtension指代可擴展的設置,其中:

  • EKU (擴展) 表示可能使用已認證的公鑰的其他目的,對於自簽名證書來說,這個擴展需要包括字符串:2.5.29.37={text}1.3.6.1.5.5.7.3.3,以便指示證書用於代碼簽名;
  • 基本約束 指示證書是否是CA證書,對於自簽名證書來說,,這個擴展需要包括字符串:2.5.29.19={text},以便指示證書是最終實體(而不是CA)

其中CertStoreLocation指代證書生成后的存儲位置,但是這個位置並非文件位置,而是本地證書存儲庫中的位置

  • 如果指定的路徑是Cert:\CurrentUser或者Cert:\CurrentUser\My,那么它的默認存儲位置就是Cert:\CurrentUser\My
  • 如果指定的路徑是Cert:\LocalMachine或者Cert:\LocalMachine\My,那么它的默認存儲位置就是Cert:\LocalMachine\My
  • 你必須指定Cert:\CurrentUser\My或者Cert:\LocalMachine\My其中一個,暫時不支持其他位置設定。

如果要查看本地存儲的證書,可以通過如下命令:

Set-Location Cert:\CurrentUser\My
Get-ChildItem | Format-Table Subject, FriendlyName, Thumbprint

說完這么多,現在搞懂概念之后,我們可以打個比如了:

New-SelfSignedCertificate -Type Custom -Subject "CN=Contoso Software, O=Contoso Corporation, C=US" -KeyUsage DigitalSignature -FriendlyName "HelloSparsePackage-SelfSignedCertificate-001" -CertStoreLocation "Cert:\CurrentUser\My" -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3", "2.5.29.19={text}")

image

太棒了,一氣呵成!

接下來,我們可以執行查詢命令看看。

Set-Location Cert:\CurrentUser\My
Get-ChildItem | Format-Table Subject, FriendlyName, Thumbprint

image

確實找到了。

如果要刪除本地存儲的證書,可以通過如下命令:

Remove-Item Cert:$TargetCertPath\$Thumbprint

例如:

Remove-Item Cert:\CurrentUser\My\492A496BDA7304061662DE55C533B4B657902A53
  1. 導出自簽名證書

https://docs.microsoft.com/zh-cn/powershell/module/pki/export-pfxcertificate

可以通過Export-PfxCertificate命令把本地存儲的證書導出到個人信息交換(PFX)文件中。

第一種是采用攜帶密碼的方式導出,使用-Password參數。

$password = ConvertTo-SecureString -String <Your Password> -Force -AsPlainText
Export-PfxCertificate -cert "Cert:\CurrentUser\My\<Certificate Thumbprint>" -FilePath <FilePath>.pfx -Password $password

其中-cert指代待導出的本地存儲證書的路徑,它是由存儲目錄+證書指紋組成的,例如:Cert:\CurrentUser\My\0AC036CD37F5FF52B41F64F7B985E534E4E84EE0

其中-FilePath指代導出的個人信息交換(PFX)文件的位置,這里需要指定一個絕對路徑,並且是帶格式后綴.pfx的,例如:C:\HelloSparsePackage-SelfSignedCertificate-001.pfx

其中-Password指代導出時設定的密碼,但是我們需要將其轉變為安全的字符串,所以通常先在前面把它准備好。例如:$password = ConvertTo-SecureString -String "1234567" -Force -AsPlainText

綜上所述,我們就可以來舉個例子:

$password = ConvertTo-SecureString -String "1234567" -Force -AsPlainText
Export-PfxCertificate -cert "Cert:\CurrentUser\My\0AC036CD37F5FF52B41F64F7B985E534E4E84EE0" -FilePath 'C:\TempSpace\HelloSparsePackage\Certificate\HelloSparsePackage-SelfSignedCertificate-001.pfx' -Password $password

image

最終得到了名為HelloSparsePackage-SelfSignedCertificate-001.pfx的個人信息交換(PFX)文件。

image

第二種是采用白名單訪問方式導出,使用-ProtectTo參數。

Export-PfxCertificate -cert Cert:\CurrentUser\My\<Certificate Thumbprint> -FilePath <FilePath>.pfx -ProtectTo <Username or group name>

其中-ProtectTo指代允許指定的用戶名或用戶組在沒有密碼的情況下訪問這個密鑰,格式采用域+用戶名,例如:contoso\billb99,如果多組可以采用:-ProtectTo "contoso\billb99", "contoso\johnj99"

注意,這種方式要求具備Windows Server® 2012及其以上版本的域控制功能,所以其實對一般用戶來說,無法采用這種方式。

使用SignTool對應用包進行簽名

https://docs.microsoft.com/zh-cn/windows/msix/package/sign-app-package-using-signtool

SignTool是命令行工具,用於對應用包或帶有證書的捆綁包進行數字簽名。證書可以由用戶創建(用於測試目的)或由公司頒發(用於分發)。登錄應用包可驗證用戶登錄后應用數據未經更改,並且可確認登錄用戶或公司的身份。SignTool可對已加密或未加密的應用包和捆綁包進行簽名

  1. 確認本地安裝的SignTool的路徑

根據不同的系統架構版本,它的位置會存在差異,對X86和X64系統而言,他們的路徑位置應該位於:

  • x86: C:\Program Files (x86)\Windows Kits\10\bin\<sdk version\x86\SignTool.exe
  • x64: C:\Program Files (x86)\Windows Kits\10\bin\<sdk version\x64\SignTool.exe

對我當前的Windows 11來說,根據這個指引找的路徑是:

C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64\signtool.exe

image

  1. 確定簽名用的哈希算法

在使用SignTool對你的應用包或捆綁包進行簽名時,SignTool中所用的哈希算法必須與你用於打包應用的算法相同。

對使用了MakeAppx.exe的應用包簽名時,它的默認簽名算法是SHA256

要找出打包應用時用到了哪種哈希算法,則需要提取應用包的內容並檢查AppxBlockMap.xml文件的BlockMap元素。

查看這個信息有兩種辦法,一種是通過MakeAppx命令直接解壓MSIX包,另外一種方法,直接用壓縮軟件把它解開。

MakeAppx unpack /p <input package name> /d <output directory>

例如:

cd 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64\'
.\makeappx.exe unpack /p 'C:\TempSpace\HelloSparsePackage\Msix\TestPackage.msix' /d 'C:\TempSpace\HelloSparsePackage\Template-Unpack\'

image

回歸正題,我們需要看看AppxBlockMap.xml文件的BlockMap元素寫了什么。

<BlockMap xmlns="http://schemas.microsoft.com/appx/2010/blockmap" xmlns:b4="http://schemas.microsoft.com/appx/2021/blockmap" IgnorableNamespaces="b4" HashMethod="http://www.w3.org/2001/04/xmlenc#sha256">...

我們看到這里有個"哈希方法(HashMethod)",它的值是http://www.w3.org/2001/04/xmlenc#sha256,那么它和我們要確認的哈希算法之間的關系是:

HashMethod 值 哈希算法
http://www.w3.org/2001/04/xmlenc#sha256 SHA256
http://www.w3.org/2001/04/xmldsig-more#sha384 SHA384
http://www.w3.org/2001/04/xmlenc#sha512 SHA512

所以這里我們能確認的是,當前MSIX包采用的打包哈希算法就是SHA256

通過命令對MSIX包簽名

https://docs.microsoft.com/zh-CN/windows/win32/seccrypto/signtool

如果我們要基於個人信息交換(PFX)文件進行簽名,那么可以采用:

SignTool sign /fd <Hash Algorithm> /a /f <Path to Certificate>.pfx /p <Your Password> <File path>.msix

其中/fd指代簽名是采用何種哈希算法,其完整示例比如:/fd SHA256

其中/a指代讓工具自動選擇最合適的證書進行簽名。

其中/f指代個人信息交換(PFX)文件的路徑,而/p指代它的訪問密碼,其完整示例比如:/f 'C:\H.pfx' /p '123457'

其中<File path>.msix指代了待被簽名的MSIX包的完整路徑,例如:C:\demo.msix

甚至我們還可以加蓋時間戳,使用參數:/t http://timestamp.digicert.com,但是這個會增加簽名的時間哈。

綜上所述,我們就可以來舉個例子:

cd 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.22000.0\x64\'
.\signtool.exe sign /fd SHA256 /a /f 'C:\TempSpace\HelloSparsePackage\Certificate\HelloSparsePackage-SelfSignedCertificate-001.pfx' /t 'http://timestamp.digicert.com' /p '1234567' 'C:\TempSpace\HelloSparsePackage\Msix\TestPackage.msix'
.\signtool.exe sign /fd SHA256 /a /f 'C:\TempSpace\HelloSparsePackage\Certificate\HelloSparsePackage-SelfSignedCertificate-001.pfx' /p '1234567' 'C:\TempSpace\HelloSparsePackage\Msix\TestPackage.msix'
Done Adding Additional Store
Successfully signed: C:\TempSpace\HelloSparsePackage\Msix\TestPackage.msix

image

我們需要注意這前后的變化,在之前,這個MSIX是沒有簽名的:

image

完成這一步之后,它有數字簽名了:

image

創建一個經典的Win32程序配置

https://docs.microsoft.com/zh-cn/windows/win32/sbscs/application-manifests

為了支持不經過UWP激活管道的CreateProcess()方案,您的應用程序必須使用經典的Win32風格的application.manifest,在新的<msix>元素下聲明您的應用程序的身份屬性。在清單中定義的值在其可執行程序啟動時用於確定您的應用程序的身份,並且必須與您的稀疏包的AppxManifest.xml中聲明的值一致

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

packageName(上面)對應於Namepublisher對應於Sparse包的<Identity>元素中的Publisher

<Identity Name="PhotoStoreDemo" Publisher="CN=Contoso" … />

applicationId對應於在Sparse包中聲明的這個應用程序的<Application>元素的Id屬性。

Applications>
<Application Id="PhotoStoreDemo"…>
…

要在Visual studio中向現有項目添加經典的Win32清單,可在應用程序節點中右鍵單擊|添加|新項目|Visual C#|應用程序清單文件。清單文件的命名慣例是,它必須與您的應用程序的.exe名稱相同,並具有.manifest擴展名,在本例中我將其命名為 "PhotoStoreDemo.exe.manifest"。

這里需要注意的是,這個應用程序清單的.Msix元素,只有在Windows 10 v2004及其以上版本才能識別並支持。

其中msix元素必須在urn:schemas-microsoft-com:msix.v1的命名空間中。

屬性 說明
publisher 介紹發布服務器信息。此值必須與稀疏包清單中的Identity元素中的Publisher特性匹配。
packageName 描述包的內容。此值必須與稀疏包清單中的Identity元素的Name特性匹配。
applicationId 應用程序的唯一標識符。此值必須與稀疏包清單中的應用程序Application元素的Id特性匹配。

添加應用程序清單

在項目上右鍵"添加"-"新建項"。

image

進入"添加新項"對話框,找到"應用程序清單(僅限Windows)"。

image

這里命名必須和應用程序的程序集帶后綴名稱一致,比如:DemoForSparseWPF.exe.manifest

image

生成后項目屬性里面的清單會自動關聯到它。

image

不過從默認得到的模板來看,里面還是蠻復雜的,為很多場景做了舉例。

image

定制稀疏包的清單內容

有了應用程序清單文件,我們就可以定制添加需要的清單內容了,先打個草稿,這里我們需要和稀疏包的清單文件保持一致,所以確定下來的內容是:

<msix xmlns="urn:schemas-microsoft-com:msix.v1"
    publisher="CN=Contoso Software, O=Contoso Corporation, C=US"
    packageName="DemoForSparsePackage"
    applicationId="Contoso.DemoForSparsePackage"
    />

另外清單文件里面,還有個assemblyIdentity元素的名稱name,也一起改吧,這個根據對應的程序名稱來就行。

我們把這個msix補充在清單文件的assemblyIdentity節點后面。

image

<?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="DemoForSparseWPF.App"/>
  <msix xmlns="urn:schemas-microsoft-com:msix.v1"
    publisher="CN=Contoso Software, O=Contoso Corporation, C=US"
    packageName="DemoForSparsePackage"
    applicationId="Contoso.DemoForSparsePackage"
    />
...

利用你的應用程序的稀疏包的優勢

如前所述,為你的應用程序創建一個稀疏包使你的Win32應用程序更容易與操作系統深度集成,並利用諸如BackgroundTasks、共享、通知和瓷磚等功能。讓我們來看看我們的樣本應用程序是如何運行和使用稀疏包來注冊為一個共享目標並利用UWP激活的。

我們的樣本中的工作流程看起來是這樣的:

  1. 在稀疏包AppxManifest.xml聲明我們的應用程序是一個共享目標
  2. 向操作系統注冊我們的應用程序的稀疏包
  3. 重新啟動應用程序並處理激活類型

使用實例 - 在稀疏包AppxManifest.xml中聲明你的應用程序是一個共享目標。

我們的示例應用程序通過在稀疏包AppxManifest.xml中聲明windows.ShareTarget應用程序擴展來注冊為一個共享目標

<Extensions>
    <uap:Extension Category="windows.shareTarget">
        <uap:ShareTarget Description="Send to PhotoStoreDemo">
            <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>

所以這個AppxManifest.xml文件我們修改成:

	...
	</Applications>
	<Extensions>
		<uap:Extension Category="windows.shareTarget">
			<uap:ShareTarget Description="發送到SparsePackageDemo">
				<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>
</Package>

image

注冊一個稀疏包

為了利用稀疏包,你的應用程序需要在系統中注冊簽名的包。你可以在第一次運行時注冊該包,或者你也可以在安裝其他Win32工件時注冊該包,如果你使用MSI這樣的安裝程序。要使用MSI安裝軟件包,你需要使用自定義動作。在我們的示例應用程序中,我們在第一次運行時注冊稀疏包。當我們的應用程序被啟動時,我們檢查它是否以身份信息運行(身份信息或沒有身份信息是稀疏包是否被注冊/安裝的信號)如果應用程序沒有以身份信息運行,我們就注冊稀疏包並重新啟動應用程序。這預計只在首次運行時發生一次。要看我們如何確定應用程序是否以身份運行,如果你想了解更多背景,請看ExecutionMode類和這篇帖子。

這就是我們應用程序中的代碼的樣子:

//if app isn’t running with identity, register its sparse package
if (!ExecutionMode.IsRunningWithIdentity())
{
    string externalLocation = @"C:\<App_Install_location_root>\";
    string sparsePkgPath = @"C:\<App_Install_location_root>\PhotoStoreDemo.msix";

    //Attempt registration
    if (registerSparsePackage(externalLocation, sparsePkgPath))
    {
        //Registration succeded, restart the app to run with identity
        System.Diagnostics.Process.Start(Application.ResourceAssembly.Location, arguments: cmdArgs?.ToString());
    }
    else //Registration failed, run without identity
    {
        Debug.WriteLine("Package Registation failed, running WITHOUT Identity");
        SingleInstanceManager wrapper = new SingleInstanceManager();
        wrapper.Run(cmdArgs);
    }
}

而這是上面調用的處理包注冊的registerSparsePackage方法:

Using Windows.Management.Deployment
…
private static bool registerSparsePackage(string externalLocation, string sparsePkgPath)
{
    bool registration = false;
    try
    {
        Uri externalUri = new Uri(externalLocation);
        Uri packageUri = new Uri(sparsePkgPath);
        PackageManager packageManager = new PackageManager();
        //Set the externalLocation where your Win32 artifacts will be installed
        //Anything not in the package but referenced by your AppxManifest.xml needs to to be under this location
        var options = new AddPackageOptions();
        options.ExternalLocationUri = externalUri;

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

為了注冊稀疏包,你需要使用PackageManager AddPackageByUriAsync(packageUri, addPackageOptions)API。該API接收你簽名的稀疏包的位置作為URI和一個AddPackageOptions對象。你需要創建一個AddpackageOptions對象,並將ExternalLocationUri屬性設置為URI,即在稀疏包中被引用的Win32工件(如應用程序可執行文件)將被安裝的位置。

處理應用程序的激活

生成並注冊稀疏包

為稀疏包創建程序包清單

生成稀疏包並為稀疏包簽名

將程序包標識符元數據添加到桌面應用程序清單

在運行時注冊稀疏包

使用打包擴展將桌面應用與Windows集成

https://docs.microsoft.com/zh-cn/windows/apps/desktop/modernize/desktop-to-uwp-extensions

如果桌面應用具有程序包標識符,你可通過程序包清單中的預定義擴展,使用擴展將應用與Windows 10及更高版本進行集成。

例如,使用擴展創建一個防火牆例外,使應用成為某一文件類型的默認應用程序,或將“開始”磁貼指向你的應用。若要使用擴展,只需將某些XML添加到應用的程序包清單文件。不需要任何代碼。

獲取打包應用的激活信息

https://docs.microsoft.com/zh-cn/windows/apps/desktop/modernize/get-activation-info-for-packaged-apps

從Windows 10 v1809版開始,經過打包的桌面應用可以調用AppInstance.GetActivatedEventArgs方法,在啟動過程中檢索某些類型的應用激活信息。例如,可以調用此方法獲取通過打開文件、單擊交互式toast或使用協議激活應用的相關信息。從Windows 10 v2004版開始,使用稀疏包的應用中也支持此功能

代碼示例

下面的代碼示例演示如何通過Windows窗體應用中的Main函數調用AppInstance.GetActivatedEventArgs方法。對於應用支持的每個激活類型,將args返回值強制轉換為相應的事件args類型。此代碼示例假定Handlexxx方法是在其他地方定義的專用激活處理程序代碼。

static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    var args = AppInstance.GetActivatedEventArgs();
    switch (args.Kind)
    {
        case ActivationKind.Launch:
            HandleLaunch(args as LaunchActivatedEventArgs);
            break;
        case ActivationKind.ToastNotification:
            HandleToastNotification(args as ToastNotificationActivatedEventArgs);
            break;
        case ActivationKind.VoiceCommand:
            HandleVoiceCommand(args as VoiceCommandActivatedEventArgs);
            break;
        case ActivationKind.File:
            HandleFile(args as FileActivatedEventArgs);
            break;
        case ActivationKind.Protocol:
            HandleProtocol(args as ProtocolActivatedEventArgs);
            break;
        case ActivationKind.StartupTask:
            HandleStartupTask(args as StartupTaskActivatedEventArgs);
            break;
        default:
            HandleLaunch(null);
            break;
    }

支持的激活類型

可以使用AppInstance.GetActivatedEventArgs方法從下表中列出的一組受支持的事件args對象中檢索激活信息。其中一些激活類型要求使用程序包清單中的一個程序包擴展。

僅Windows 10 v2004版及更高版本支持ShareTargetActivatedEventArgs激活信息。Windows 10 v1809版及更高版本支持所有其他激活信息類型。

事件args類型 程序包擴展 相關文檔
ShareTargetActivatedEventArgs uap:ShareTarget 使桌面應用程序成為共享目標
ProtocolActivatedEventArgs uap:Protocol 使用協議啟動應用程序
ToastNotificationActivatedEventArgs desktop:ToastNotificationActivation 來自桌面應用的Toast通知。
StartupTaskActivatedEventArgs desktop:StartupTask 用戶登錄Windows時啟動可執行文件
FileActivatedEventArgs uap:FileTypeAssociation 將打包的應用程序與一組文件類型相關聯
VoiceCommandActivatedEventArgs 處理激活和執行語音命令
LaunchActivatedEventArgs

使用新式UWP組件擴展桌面應用

https://docs.microsoft.com/zh-cn/windows/apps/desktop/modernize/desktop-to-uwp-extend

某些Windows 10體驗(例如,支持觸摸的UI頁面)必須在新式應用容器內部運行。如果要添加這些體驗,請用UWP項目和Windows運行時組件擴展桌面應用程序。

在許多情況下,你可以直接從桌面應用程序中調用Windows運行時API,因此在查看本指南前,請參閱面向Windows 10的增強

本文中所述的功能要求桌面應用具有程序包標識符(通過在MSIX包中打包桌面應用或使用稀疏包授予應用標識)

如果你准備好了,那我們就開始吧。

在桌面應用中調用Windows運行時API

https://docs.microsoft.com/zh-cn/windows/apps/desktop/modernize/desktop-to-uwp-enhance

桌面應用項目以使用WindowsOS提供的Windows運行時(WinRT)API,並將新式Windows11和Windows10體驗添加到桌面應用。

桌面應用中不支持某些Windows運行時(WinRT)API。有關詳細信息,請參閱桌面應用中不支持的Windows運行時API。

修改.NET項目以使用Windows運行時API

有幾個用於.NET項目的選項:

  • 從.NET5開始,可以在項目文件中添加目標框架名字對象(TFM),用於訪問WinRTAPI。此選項支持面向Windows 10 v1809版或更高版本的項目。
  • 對於早期版本的.NET,可以安裝Microsoft.Windows.SDK.Contracts的NuGet包,以便將所有必要的引用添加到項目中。此選項支持面向Windows 10 v1803版或更高版本的項目。
  • 如果你的項目同時面向.NET5(或更高版本)和早期版本的.NET等多個目標,可將項目文件配置為同時使用這兩個選項。

實踐

https://github.com/TaylorShi/HelloSparsePackage

創建解決方案HelloSparsePackage

dotnet new sln -o HelloSparsePackage

image

cd .\HelloSparsePackage\

image

explorer.exe .

image

創建Windows應用程序打包項目DemoForSparsePacking

在Visual Studio中,在解決方案HelloSparsePackage上右鍵選擇"添加"->"新建項目",打開新建項目對話框。

image

語言項選"所有語言",平台項選"Windows",項目類型項選"桌面",往下拉,找到"Windows應用程序打包項目",點擊"下一步"。

image

輸入新項目名DemoForSparsePacking,然后點擊"創建"按鈕即可完成項目創建。

image

在"新式通用Windows平台項目",這里我們就保持默認,目標版本和最低版本都按推薦值來吧,最后點擊"確定"即可。

image

接下來,Windows應用程序打包項目DemoForSparsePacking就創建好了。

image

創建.Net Framework的Winforms項目DemoForSparseWinforms

在Visual Studio中,在解決方案HelloSparsePackage上右鍵選擇"添加"->"新建項目",打開新建項目對話框。

image

語言項選"C#",平台項選"Windows",項目類型項選"桌面",往下拉,找到"Windows窗體應用(.Net Framework)",點擊"下一步"。

image

輸入新項目名DemoForSparseWinforms,框架項選擇".Net framework 2.0",然后點擊"創建"按鈕即可完成項目創建。

image

接下來,Windows窗體應用(.Net Framework)項目DemoForSparseWinforms就創建好了。

image

創建.Net Framework的WPF項目DemoForSparseWPF

在Visual Studio中,在解決方案HelloSparsePackage上右鍵選擇"添加"->"新建項目",打開新建項目對話框。

image

語言項選"C#",平台項選"Windows",項目類型項選"桌面",往下拉,找到"WPF應用(.Net Framework)",點擊"下一步"。

image

輸入新項目名DemoForSparseWPF,框架項選擇".Net framework 4.6.1",然后點擊"創建"按鈕即可完成項目創建。

image

接下來,WPF應用(.Net Framework)項目DemoForSparseWPF就創建好了。

image

案例分析:WinRAR

新聞

2022年1月25日,老牌壓縮軟件WinRAR迎來了6.10正式版更新,更新提供了對Windows 11右鍵菜單的支持。

image

安裝

目錄

image

我們看到安裝目錄下面有個RarExtPackage.msix,接下來打開看看它。

解剖

RarExtPackage.msix解開,里面一些文件。

image

右邊就是一些視覺資產文件,它這個比較簡單了,只包括:

  • RarExtLogo.altform-unplated_targetsize-32.png
  • RarExtLogo.altform-unplated_targetsize-48.png
  • RarExtLogo.altform-unplated_targetsize-64.png
  • Square150x150Logo.png
  • StoreLogo.png

基本上也夠用了。反映到AppxManifest.xml中來看呢,對應了

<Properties>
    <DisplayName>WinRAR</DisplayName>
    <PublisherDisplayName>win.rar GmbH</PublisherDisplayName>
    <Logo>StoreLogo.png</Logo>
    <desktop6:RegistryWriteVirtualization>disabled</desktop6:RegistryWriteVirtualization>
    <desktop6:FileSystemWriteVirtualization>disabled</desktop6:FileSystemWriteVirtualization>
    <uap10:AllowExternalContent>true</uap10:AllowExternalContent>
</Properties>
<Applications>
    <Application Id="WinRAR.ShellExtension" Executable="RarExtInstaller.exe" uap10:TrustLevel="mediumIL" uap10:RuntimeBehavior="win32App">
        <uap:VisualElements AppListEntry="none" DisplayName="WinRAR" Description="RarExtInstaller.exe" BackgroundColor="transparent" Square150x150Logo="Square150x150Logo.png" Square44x44Logo="RarExtLogo.png">
        </uap:VisualElements>
    </Application>
</Applications>

左邊是MSIX要求的一些描述文件了,其中AppxManifest.xml整體的看一下:

<?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:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
  xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
  xmlns:desktop6="http://schemas.microsoft.com/appx/manifest/desktop/windows10/6"
  xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
  xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
  IgnorableNamespaces="uap uap2 uap3 rescap desktop desktop4 desktop5 uap10 com">
  <Identity Name="WinRAR.ShellExtension" Publisher="CN=win.rar GmbH, O=win.rar GmbH, L=Berlin, S=Berlin, C=DE" ProcessorArchitecture="x64" Version="1.0.0.1" />
  <Properties>
    <DisplayName>WinRAR</DisplayName>
    <PublisherDisplayName>win.rar GmbH</PublisherDisplayName>
    <Logo>StoreLogo.png</Logo>
    <desktop6:RegistryWriteVirtualization>disabled</desktop6:RegistryWriteVirtualization>
    <desktop6:FileSystemWriteVirtualization>disabled</desktop6:FileSystemWriteVirtualization>
    <uap10:AllowExternalContent>true</uap10:AllowExternalContent>
  </Properties>
  <Dependencies>
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.19041.0" />
  </Dependencies>
  <Resources>
    <Resource Language="EN-US" />
  </Resources>
  <Capabilities>
    <rescap:Capability Name="runFullTrust" />
    <rescap:Capability Name="unvirtualizedResources"/>
  </Capabilities>
  <Applications>
    <Application Id="WinRAR.ShellExtension" Executable="RarExtInstaller.exe" uap10:TrustLevel="mediumIL" uap10:RuntimeBehavior="win32App">
      <uap:VisualElements AppListEntry="none" DisplayName="WinRAR" Description="RarExtInstaller.exe" BackgroundColor="transparent" Square150x150Logo="Square150x150Logo.png" Square44x44Logo="RarExtLogo.png">
      </uap:VisualElements>
      <Extensions>
        <com:Extension Category="windows.comServer">
          <com:ComServer>
            <com:SurrogateServer DisplayName="WinRAR">
              <com:Class Id="b41db860-64e4-11d2-9906-e49fadc173ca" Path="RarExt.dll" ThreadingModel="STA" />
            </com:SurrogateServer>
          </com:ComServer>
        </com:Extension>
        <desktop4:Extension Category="windows.fileExplorerContextMenus">
          <desktop4:FileExplorerContextMenus>
            <desktop5:ItemType Type="*">
              <desktop5:Verb Id="WinRARTopEntry" Clsid="b41db860-64e4-11d2-9906-e49fadc173ca" />
            </desktop5:ItemType>
            <desktop5:ItemType Type="Directory">
              <desktop5:Verb Id="WinRARTopEntry" Clsid="b41db860-64e4-11d2-9906-e49fadc173ca" />
            </desktop5:ItemType>
          </desktop4:FileExplorerContextMenus>
        </desktop4:Extension>
      </Extensions>
    </Application>
  </Applications>
</Package>

至於[Content_Types].xmlAppxBlockMap.xml我暫時覺得就沒必要看了,應該是創建MSIX包自動生成的。

案例分析:NanaZip

新聞

2021年10月31日,NanaZip基於7-Zip,因此功能和性能都和7-Zip差不多,甚至連界面也和7-Zip一個簡陋風格,除了提供最基礎的交互,沒有什么精美的設計。

image

image

功能

  • 繼承了7-Zip 21.07的所有功能。
  • 使用MSIX打包,以獲得現代部署體驗
  • 支持Windows 10/11文件管理器中的上下文菜單
  • 啟用NSIS檔案的NSIS腳本反編譯支持。(合並自7-Zip NSIS分支。)
  • 提供7-Zip執行別名,幫助用戶遷移到NanaZip。
  • 支持 Brotli,Fast-LZMA2,Lizard, LZ4, LZ5和Zstandard編解碼器。(合並自7-Zip ZS分支。)

安裝

a. 從微軟官方商店獲取

NanaZip是一個開放源碼的文件存檔器,旨在為現代的Windows體驗,從著名的開放源碼文件存檔器7-Zip的源代碼分叉出來。

b. 從Github發布頁獲取

目錄

image

這是一個MSIX打包的應用。

解剖

其中AppxManifest.xml整體的看一下:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Package IgnorableNamespaces="uap rescap desktop uap3 com desktop4 desktop5 uap8 virtualization build" xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10" xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3" xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10" xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4" xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5" xmlns:uap8="http://schemas.microsoft.com/appx/manifest/uap/windows10/8" xmlns:virtualization="http://schemas.microsoft.com/appx/manifest/virtualization/windows10" xmlns:build="http://schemas.microsoft.com/developer/appx/2015/build" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest">
  <Identity Name="40174MouriNaruto.NanaZipPreview" Publisher="CN=E310A153-74A9-4D81-800B-857A8D58408A" Version="1.1.153.0" ProcessorArchitecture="x64" />
  <Properties>
    <DisplayName>NanaZip Preview</DisplayName>
    <PublisherDisplayName>Kenji Mouri</PublisherDisplayName>
    <Logo>Assets\StoreLogo.png</Logo>
    <virtualization:FileSystemWriteVirtualization>
      <virtualization:ExcludedDirectories>
        <virtualization:ExcludedDirectory>$(KnownFolder:LocalAppData)</virtualization:ExcludedDirectory>
        <virtualization:ExcludedDirectory>$(KnownFolder:LocalAppDataLow)</virtualization:ExcludedDirectory>
        <virtualization:ExcludedDirectory>$(KnownFolder:RoamingAppData)</virtualization:ExcludedDirectory>
      </virtualization:ExcludedDirectories>
    </virtualization:FileSystemWriteVirtualization>
  </Properties>
  <Dependencies>
    <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.22000.0" />
  </Dependencies>
  <Resources>
    <Resource Language="EN-US" />
    <Resource uap:Scale="100" />
    <Resource uap:Scale="200" />
    <Resource uap:Scale="400" />
  </Resources>
  <Applications>
    <Application Id="NanaZipC" Executable="NanaZip.exe" EntryPoint="Windows.FullTrustApplication">
      <uap:VisualElements AppListEntry="none" DisplayName="NanaZip Preview" Description="NanaZip" BackgroundColor="transparent" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" />
      <Extensions>
        <uap3:Extension Category="windows.appExecutionAlias" Executable="NanaZipC.exe" EntryPoint="Windows.FullTrustApplication">
          <uap3:AppExecutionAlias>
            <desktop:ExecutionAlias Alias="NanaZipC.exe" />
            <desktop:ExecutionAlias Alias="7z.exe" uap8:AllowOverride="true" />
          </uap3:AppExecutionAlias>
        </uap3:Extension>
      </Extensions>
    </Application>
    <Application Id="NanaZipG" Executable="NanaZipG.exe" EntryPoint="Windows.FullTrustApplication">
      <uap:VisualElements AppListEntry="none" DisplayName="NanaZip Preview" Description="NanaZip" BackgroundColor="transparent" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" />
      <Extensions>
        <uap3:Extension Category="windows.appExecutionAlias" Executable="NanaZipG.exe" EntryPoint="Windows.FullTrustApplication">
          <uap3:AppExecutionAlias>
            <desktop:ExecutionAlias Alias="NanaZipG.exe" />
            <desktop:ExecutionAlias Alias="7zG.exe" uap8:AllowOverride="true" />
          </uap3:AppExecutionAlias>
        </uap3:Extension>
      </Extensions>
    </Application>
    <Application Id="NanaZip" Executable="NanaZip.exe" EntryPoint="Windows.FullTrustApplication">
      <uap:VisualElements DisplayName="NanaZip Preview" Description="NanaZip" BackgroundColor="transparent" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png">
        <uap:DefaultTile ShortName="NanaZip" Wide310x150Logo="Assets\Wide310x150Logo.png" Square310x310Logo="Assets\LargeTile.png" Square71x71Logo="Assets\SmallTile.png">
          <uap:ShowNameOnTiles>
            <uap:ShowOn Tile="wide310x150Logo" />
            <uap:ShowOn Tile="square150x150Logo" />
            <uap:ShowOn Tile="square310x310Logo" />
          </uap:ShowNameOnTiles>
        </uap:DefaultTile>
      </uap:VisualElements>
      <Extensions>
        <uap3:Extension Category="windows.appExecutionAlias" Executable="NanaZip.exe" EntryPoint="Windows.FullTrustApplication">
          <uap3:AppExecutionAlias>
            <desktop:ExecutionAlias Alias="NanaZip.exe" />
            <desktop:ExecutionAlias Alias="7zFM.exe" uap8:AllowOverride="true" />
          </uap3:AppExecutionAlias>
        </uap3:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_001">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - 001 Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.001</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_7z">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - 7z Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.7z</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_arj">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - arj Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.arj</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_bz2">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - bz2 Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.bz2</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_bzip2">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - bzip2 Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.bzip2</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_cab">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - cab Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.cab</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_cpio">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - cpio Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.cpio</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_deb">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - deb Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.deb</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_dmg">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - dmg Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.dmg</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_esd">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - esd Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.esd</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_fat">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - fat Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.fat</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_gz">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - gz Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.gz</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_gzip">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - gzip Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.gzip</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_hfs">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - hfs Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.hfs</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_iso">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - iso Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.iso</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_lha">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - lha Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.lha</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_liz">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - liz Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.liz</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_lz">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - lz Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.lz</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_lz4">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - lz4 Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.lz4</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_lz5">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - lz5 Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.lz5</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_lzh">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - lzh Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.lzh</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_lzma">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - lzma Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.lzma</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_ntfs">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - ntfs Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.ntfs</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_rar">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - rar Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.rar</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_rpm">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - rpm Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.rpm</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_squashfs">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - squashfs Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.squashfs</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_swm">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - swm Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.swm</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_tar">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - tar Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.tar</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_taz">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - taz Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.taz</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_tbz">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - tbz Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.tbz</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_tbz2">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - tbz2 Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.tbz2</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_tgz">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - tgz Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.tgz</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_tlz">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - tlz Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.tlz</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_tpz">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - tpz Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.tpz</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_txz">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - txz Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.txz</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_vhd">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - vhd Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.vhd</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_vhdx">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - vhdx Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.vhdx</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_wim">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - wim Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.wim</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_xar">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - xar Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.xar</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_xz">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - xz Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.xz</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_z">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - z Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.z</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_zip">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - zip Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.zip</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <uap:Extension Category="windows.fileTypeAssociation">
          <uap:FileTypeAssociation Name="archivetype_zst">
            <uap:Logo>Assets\ArchiveFile.png</uap:Logo>
            <uap:DisplayName>NanaZip - zst Archive</uap:DisplayName>
            <uap:SupportedFileTypes>
              <uap:FileType>.zst</uap:FileType>
            </uap:SupportedFileTypes>
          </uap:FileTypeAssociation>
        </uap:Extension>
        <desktop4:Extension Category="windows.fileExplorerContextMenus">
          <desktop4:FileExplorerContextMenus>
            <desktop5:ItemType Type="Directory">
              <desktop5:Verb Id="NanaZipShellExtension" Clsid="469D94E9-6AF4-4395-B396-99B1308F8CE5" />
            </desktop5:ItemType>
            <desktop5:ItemType Type="*">
              <desktop5:Verb Id="NanaZipShellExtension" Clsid="469D94E9-6AF4-4395-B396-99B1308F8CE5" />
            </desktop5:ItemType>
          </desktop4:FileExplorerContextMenus>
        </desktop4:Extension>
        <com:Extension Category="windows.comServer">
          <com:ComServer>
            <com:SurrogateServer DisplayName="NanaZip Shell Extension">
              <com:Class Id="469D94E9-6AF4-4395-B396-99B1308F8CE5" Path="NanaZipShellExtension.dll" ThreadingModel="STA" />
            </com:SurrogateServer>
          </com:ComServer>
        </com:Extension>
      </Extensions>
    </Application>
  </Applications>
  <Capabilities>
    <rescap:Capability Name="runFullTrust" />
  </Capabilities>
  <build:Metadata>
    <build:Item Name="Microsoft.Build.DesktopBridge.Tasks.dll" Version="4.6.30319.200" />
    <build:Item Name="TargetFrameworkMoniker" Value="native,Version=v0.0" />
    <build:Item Name="VisualStudio" Version="17.0" />
    <build:Item Name="OperatingSystem" Version="10.0.22000.434 (WinBuild.160101.0800)" />
    <build:Item Name="Microsoft.Build.AppxPackage.dll" Version="17.0.31912.81" />
    <build:Item Name="ProjectGUID" Value="9a119a76-97cb-4490-b8c2-651576cb9302" />
    <build:Item Name="MakePri.exe" Version="10.0.22000.194 (WinBuild.160101.0800)" />
  </build:Metadata>
  <mp:PhoneIdentity PhoneProductId="0f6c8cd6-bec0-499c-810f-28e88a3e4b62" PhonePublisherId="5865126c-fd0a-473f-9c00-925aa3a04529" />
</Package>

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM