使用外部位置封裝來授與套件識別資料
如果您有現有的傳統型應用程式,其具有自己的安裝程式,您不需要太多變更,就能從套件識別資料獲益。
許多 Windows 擴充性功能 (包括背景工作、通知、動態磚和共用目標) 都可由傳統型應用程式使用,前提是該應用程式在執行階段時具有套件識別資料。 這是因為作業系統 (OS) 必須能夠識別對應 API 的呼叫端。 請參閱需要套件識別資料的功能。
只有已封裝的應用程式在執行階段時具有套件識別資料。 如需已封裝、未封裝及在外部位置進行封裝的應用程式定義,請參閱部署概觀。
- 在 Windows 10 版本 2004 和更早版本中,將套件識別資料授與應用程式的唯一方法是將其封裝在已簽署的 MSIX 套件中 (請參閱從您的程式碼建置 MSIX 套件)。 在該案例中,身分識別會指定於套件資訊清單,而 MSIX 部署管線會根據資訊清單中的資訊來處理身分識別註冊。 套件資訊清單中參考的所有內容都會出現在 MSIX 套件內。
- 但是從 Windows 10 版本 2004 開始,您只要建置具有外部位置的套件並向您的應用程式進行註冊,即可將套件識別資料授與應用程式。 這麼做會將其轉換成已封裝的應用程式;具體而言是具有外部位置的已封裝應用程式。 這是因為有些傳統型應用程式尚未準備好讓其所有內容都存在於 MSIX 套件內。 因此,這項支援可讓這類應用程式具有套件識別資料;因此,能夠使用需要套件識別資料的 Windows 擴充性功能。 如需詳細背景資訊,請參閱部落格文章身分識別、註冊和啟用非封裝的 Win32 應用程式。
若要建置具有外部位置的套件並且進行註冊 (將套件識別資料授與您的應用程式),請遵循以下步驟。
重要概念
下列功能可讓未封裝的傳統型應用程式取得套件識別資料。
具有外部位置的套件
具有外部位置的套件包含封裝資訊清單,但沒有其他應用程式二進位檔和內容。 具有外部位置的套件其資訊清單可以參考在預先決定的外部位置中套件外部的檔案。 如上所述,這項支援可讓尚未準備好讓其所有內容出現在 MSIX 套件內的應用程式,使用需要套件識別資料的 Windows 擴充性功能。
注意
使用具有外部位置的套件的傳統型應用程式不會收到透過 MSIX 套件完全部署的部分優點。 這些優點包括防篡改保護、在鎖定位置安裝,以及作業系統在部署、執行階段和解除安裝時的完整管理。
允許外部內容
為了支援具有外部位置的套件,封裝資訊清單結構描述現在支援 Properties 元素之下的選擇性 uap10:AllowExternalContent 元素。 這可讓您的套件資訊清單參考套件外部的內容 (在磁片上的特定位置)。
例如,如果您現有的未封裝傳統型應用程式在 C:\Program Files\MyDesktopApp 中安裝應用程式可執行檔和其他內容,您可以建立具有外部位置的套件,其包含資訊清單中的 uap10:AllowExternalContent 元素。 在應用程式的安裝過程中,或第一次執行應用程式時,您可以安裝具有外部位置的套件,並將 C:\Program Files\MyDesktopApp\ 宣告為應用程式將使用的外部位置。
為具有外部位置的套件建立封裝資訊清單
您必須先建立封裝資訊清單 (名為 AppxManifest.xml 的檔案),以宣告傳統型應用程式的套件識別資料中繼資料及其他必要的詳細資料,才能建置具有外部位置的套件。 為具有外部位置的套件建立封裝資訊清單的最簡單方式,就是使用下面的範例,並使用結構描述參考為您的應用程式進行自訂。
確定套件資訊清單包含下列項目:
- Identity 元素,可描述傳統型應用程式的身分識別屬性。
- Properties 元素之下的 uap10:AllowExternalContent 元素。 此元素應獲派
true
值,該值可讓您的套件資訊清單參考套件外部的內容 (在磁片上的特定位置)。 在稍後的步驟中,您將會從在您的安裝程式或應用程式中執行的程式碼註冊具有外部位置的套件時,指定外部位置的路徑。 您在資訊清單中所參考的任何內容 (不在套件本身) 都應該安裝到外部位置。 - TargetDeviceFamily 元素的 MinVersion 屬性應該設定為
10.0.19000.0
或更新版本。 - Application 元素的 TrustLevel=mediumIL 和 RuntimeBehavior=Win32App 屬性會宣告與具有外部位置的套件相關聯的傳統型應用程式,其執行方式類似於標準未封裝的傳統型應用程式,而不需登錄和檔案系統虛擬化和其他執行階段變更。
下列範例顯示具有外部位置資訊清單的套件 (AppxManifest.xml
) 的完整內容。 此資訊清單包含需要套件識別資料的 windows.sharetarget
擴充功能。
<?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="ContosoPhotoStore" ProcessorArchitecture="x64" Publisher="CN=Contoso" Version="1.0.0.0" />
<Properties>
<DisplayName>ContosoPhotoStore</DisplayName>
<PublisherDisplayName>Contoso</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="ContosoPhotoStore" Executable="ContosoPhotoStore.exe" uap10:TrustLevel="mediumIL" uap10:RuntimeBehavior="win32App">
<uap:VisualElements AppListEntry="none" DisplayName="Contoso PhotoStore" Description="Demonstrate photo app" 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>
<Extensions>
<uap:Extension Category="windows.shareTarget">
<uap:ShareTarget Description="Send to ContosoPhotoStore">
<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>
</Application>
</Applications>
</Package>
建置具有外部位置的套件並且簽署
建立封裝資訊清單之後,請使用 Windows SDK 中的 MakeAppx.exe 工具來建置具有外部位置的套件。 因為具有外部位置的套件不包含資訊清單中所參考的檔案,所以您必須指定 /nv
選項,以略過套件的語意驗證。
下列範例示範如何從命令列建立具有外部位置的套件。
MakeAppx.exe pack /d <path to directory that contains manifest> /p <output path>\MyPackage.msix /nv
您必須使用目標電腦上受信任的憑證來簽署具有外部位置的套件,才能順利將其安裝在目標電腦上。 您可以建立新的自我簽署憑證以供開發之用,並使用 Windows SDK 中提供的 SignTool 來簽署具有外部位置的套件。
下列範例示範如何從命令列簽署具有外部位置的套件。
SignTool.exe sign /fd SHA256 /a /f <path to certificate>\MyCertificate.pfx /p <certificate password> <path to package with external location>\MyPackage.msix
將套件識別中繼資料新增至傳統型應用程式資訊清單
您也必須在傳統型應用程式中包含並存應用程式資訊清單。 請參閱應用程式資訊清單 (這是宣告 DPI 感知之類的項目,並在建置期間內嵌至應用程式的 .exe
檔案)。 在該檔案中,包含 msix 元素,其中包含宣告您應用程式識別屬性的屬性。 當可執行檔啟動時,作業系統會使用這些屬性的值來判斷您應用程式的身分識別。
下列範例會顯示含有 msix 元素的並存應用程式資訊清單。
<?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="Contoso.PhotoStoreApp"/>
<msix xmlns="urn:schemas-microsoft-com:msix.v1"
publisher="CN=Contoso"
packageName="ContosoPhotoStore"
applicationId="ContosoPhotoStore"
/>
</assembly>
msix 元素的屬性,必須符合您具有外部位置的套件的封裝資訊清單中的這些值:
- packageName 和 publisher 屬性必須分別符合套件資料清單中 Identity 元素的 Name 和 Publisher 屬性。
- applicationId 屬性必須符合套件資訊清單中 Application 元素的 Id 屬性。
在執行階段註冊具有外部位置的套件
若要將套件識別資料授與您的傳統型應用程式,您的應用程式必須使用 PackageManager 類別的 AddPackageByUriAsync 方法來註冊具有外部位置的套件。 Windows 10 版本 2004 起可以取得此方法。 您可以將程式碼新增至應用程式,以在第一次執行應用程式時註冊具有外部位置的套件,也可以在安裝傳統型應用程式時執行程式碼來註冊該套件 (例如,如果您使用 MSI 來安裝傳統型應用程式,可以從自訂動作執行此程式碼)。
下列範例示範如何註冊具有外部位置的套件。 此程式碼會建立 AddPackageOptions 物件,其中包含您的套件資訊清單可參考套件外部內容的外部位置路徑。 然後,程式碼會將此物件傳遞至 AddPackageByUriAsync 方法,以註冊具有外部位置的套件。 此方法也會將已簽署具有外部位置的套件的位置接收為 URI。 如需更完整的範例,請參閱相關範例應用程式中的 StartUp.cs
程式碼檔案 (請參閱本主題中的範例應用程式一節)。
private static bool registerPackageWithExternalLocation(string externalLocation, string pkgPath)
{
bool registration = false;
try
{
Uri externalUri = new Uri(externalLocation);
Uri packageUri = new Uri(pkgPath);
Console.WriteLine("exe Location {0}", externalLocation);
Console.WriteLine("msix Address {0}", pkgPath);
Console.WriteLine(" exe Uri {0}", externalUri);
Console.WriteLine(" msix Uri {0}", packageUri);
PackageManager packageManager = new PackageManager();
// Declare use of an external location
var options = new AddPackageOptions();
options.ExternalLocationUri = externalUri;
Windows.Foundation.IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deploymentOperation = packageManager.AddPackageByUriAsync(packageUri, options);
// Other progress and error-handling code omitted for brevity...
}
}
範例應用程式
如需可完整運作的範例應用程式,以示範如何使用具有外部位置的套件將套件識別資料授與傳統型應用程式,請參閱 SparsePackages (具有外部位置的套件) 範例。 此主題中的逐步解說會重點介紹將套件識別資料授與未封裝的應用程式的主要步驟,而範例應用程式則會提供完整範例供您作為參考。 如需建置和執行範例的詳細資訊,請參閱部落格文章身分識別、註冊及啟用非封裝 Win32 應用程式。
此範例包含下列項目:
- 名為 PhotoStoreDemo 之 WPF 應用程式的原始程式碼。 在啟動期間,應用程式會檢查其是否正以身分識別執行。 如果其不是以身分識別執行,則會註冊具有外部位置的套件,然後重新啟動應用程式。 如需執行這些步驟的程式碼,請參閱
StartUp.cs
。 - 名為
PhotoStoreDemo.exe.manifest
的並存應用程式資訊清單。 - 名為
AppxManifest.xml
的套件資訊清單。