將未封裝的應用程式與 Windows Share 整合
本文說明如何將未封裝的應用程式與 Windows Share 功能整合。 「共用」功能可讓使用者將內容從一個 Windows 應用程式共用到另一個應用程式。 未封裝的應用程式必須隨附套件身分識別,才能註冊為 [共用目標]。 註冊之後,應用程式就可以接收及處理共用檔案。
如何將未封裝的應用程式上線為「共用目標」:
- 提供具有套件身分識別的應用程式
- 實作「共用」合約
提供具有套件身分識別的未封裝應用程式
應用程式可以透過兩種方式取得套件身分識別:
- 建立新的 MSIX 安裝套件 (慣用方法) 或
- 將應用程式封裝為與目前安裝程式相容的外部位置。 這僅適用於具有現有安裝程式且無法切換至 MSIX 安裝的應用程式。
建立新的 MSIX 安裝套件
建議您在 Visual Studio 中使用 Windows 應用程式封裝專案範本,以 MSIX 封裝應用程式。 這將會包含 MSIX 套件中的所有二進位檔,並提供全新且受信任的安裝體驗。
封裝傳統型應用程式之前要注意的事項:準備封裝傳統型應用程式 (MSIX)。
請遵循在 Visual Studio 中為 MSIX 封裝設定傳統型應用程式中的步驟,為現有的應用程式專案產生套件。
注意
建立封裝專案時,請選取 Windows 10 版本 2004 (10.0;組建 19041) 或更新版本作為最低版本。
完成時,您將遵循在 Visual Studio 中封裝傳統型或 UWP 應用程式來建立套件。
與目前安裝程式相容的外部位置進行封裝
提供應用程式套件身分識別的第二種方式,就是將具有外部位置的套件新增至您的應用程式,並將其註冊至現有的安裝程式。 具有外部位置的套件是空的 MSIX 套件,其中包含具有身分識別、共用目標註冊和視覺資產的 .appxmanifest。 應用程式的二進位檔仍由應用程式現有的安裝程式管理。 註冊套件時,您必須在 API 中提供該應用程式的安裝位置。 請務必將身分識別保留在 MSIX 套件資訊清單中,並將 Win32 應用程式資訊清單與用來簽署應用程式的憑證同步。
將套件身分識別授與未封裝應用程式的步驟
這裡提供有關如何建立具有外部位置的套件的文件,包括要使用的範本資訊:使用外部位置封裝來授與套件身分識別。
GitHub 上提供完整的範例應用程式:SparsePackages (在外部位置進行封裝)。
註冊為「共用目標」
應用程式具有套件身分識別後,下一個步驟就是實作「共用」合約。 「共用」合約可讓您的應用程式接收其他應用程式的資料。
您可以遵循將封裝的應用程式與「共用工作表」整合文章中的註冊為「共用目標」一節中的相同步驟。
範例 PhotoStore 應用程式的逐步解說
在這個套件身分識別、註冊和解除封裝 Win32 應用程式共用啟用逐步解說中,您將了解如何建立具有外部位置的套件,將套件身分識別授與未封裝的 Win32 應用程式。 應用程式具有套件身分識別後,就可以將其註冊並作為「共用目標」處理啟用。 您將使用 PhotoStoreDemo 範例採取下列步驟:
- 產生
AppxManifest.xml
檔案 - 建立套件
- 簽署套件
- 註冊套件
- 處理應用程式啟用
從建立 AppxManifest.xml
檔案開始,其中包含必要的屬性,例如 <AllowExternalContent>
、身分識別、功能和共用目標延伸模組。 請確定 AppxManifest.xml
檔案中的 Publisher
、PackageName
和 ApplicationId
值符合 PhotoStoreDemo.exe.manifest
檔案中的值。 此 Publisher
值也應該符合用來簽署封裝之憑證中的值。 視需要新增視覺資產,並在 AppxManifest.xml
中參考。 在 Visual Studio 中,您可以在應用程式封裝專案中編輯 package.manifest
時使用 [視覺資產] 節點來產生所需的視覺資產。
這是允許外部內容的範例 AppxManifest.xml
程式碼片段:
<Identity Name="PhotoStoreDemo" ProcessorArchitecture="neutral" Publisher="CN=YourPubNameHere" Version="1.0.0.0" />
<Properties>
<DisplayName>PhotoStoreDemo</DisplayName>
<PublisherDisplayName>Sparse Package</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.19041.0" MaxVersionTested="10.0.19041.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">
<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>
<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>
...
這是範例 Application.exe.manifest 檔案:
<?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="PhotoStoreDemo.app"/>
<msix xmlns="urn:schemas-microsoft-com:msix.v1"
publisher="CN=YourPubNameHere"
packageName="PhotoStoreDemo"
applicationId="PhotoStoreDemo"
/>
</assembly>
接下來,若要建立具有外部位置的套件,請使用 MakeAppx.exe
工具搭配 /nv
命令來建立包含 AppxManifest.xml
檔案的套件。
範例:
MakeAppx.exe pack /d <Path to directory with AppxManifest.xml> /p <Output Path>\mypackage.msix /nv
注意
具有外部位置的套件包含封裝資訊清單,但沒有其他應用程式二進位檔和內容。 具有外部位置的套件其資訊清單可以參考在預先決定的外部位置中套件外部的檔案。
使用 SignTool.exe
,使用可信任的憑證簽署您的套件。
範例:
SignTool.exe sign /fd SHA256 /a /f <path to cert> /p <cert key> <Path to Package>
用於簽署套件的憑證,應該安裝在機器上的受信任位置。
在第一次執行應用程式時,向 Windows 註冊套件。 當應用程式自帶安裝程式時,它也應該包含已簽署的 MSIX 做為承載,並且應該將其放置在指定的位置 (例如,應用程式的安裝位置)。 應用程式在執行階段必須知道這個位置,因為該應用程式需要 MSIX 的絕對路徑才能將其註冊。 也將資產和 resources.pri
放在該應用程式的安裝位置。
下列程式碼是未封裝執行應用程式 Main 方法的範例:
[STAThread]
public static void Main(string[] cmdArgs)
{
//if app isn't running with identity, register its package with external identity
if (!ExecutionMode.IsRunningWithIdentity())
{
//TODO - update the value of externalLocation to match the output location of your VS Build binaries and the value of
//externalPkgPath to match the path to your signed package with external identity (.msix).
//Note that these values cannot be relative paths and must be complete paths
string externalLocation = Environment.CurrentDirectory;
string externalPkgPath = externalLocation + @"\PhotoStoreDemo.package.msix";
//Attempt registration
bool bPackageRegistered = false;
//bPackageRegistered = registerPackageWithExternalLocation(externalLocation, externalPkgPath);
if (bPackageRegistered)
{
//Registration succeeded, 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 Registration failed, running WITHOUT Identity");
SingleInstanceManager wrapper = new SingleInstanceManager();
wrapper.Run(cmdArgs);
}
}
...
這個範例示範如何在第一次執行應用程式時註冊 MSIX:
[STAThread]
public static void Main(string[] cmdArgs)
{
//If app isn't running with identity, register its package with external identity
if (!ExecutionMode.IsRunningWithIdentity())
{
//TODO - update the value of externalLocation to match the output location of your VS Build binaries and the value of
//externalPkgPath to match the path to your signed package with external identity (.msix).
//Note that these values cannot be relative paths and must be complete paths
string externalLocation = Environment.CurrentDirectory;
string externalPkgPath = externalLocation + @"\PhotoStoreDemo.package.msix";
//Attempt registration
if (registerPackageWithExternalLocation(externalLocation, externalPkgPath))
{
//Registration succeeded, 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 Registration failed, running WITHOUT Identity");
SingleInstanceManager wrapper = new SingleInstanceManager();
wrapper.Run(cmdArgs);
}
}
...
最後,處理應用程式的啟用:
[STAThread]
public static void Main(string[] cmdArgs)
{
//if app isn't running with identity, register its sparse package
if (!ExecutionMode.IsRunningWithIdentity())
{
...
}
else //App is registered and running with identity, handle launch and activation
{
//Handle Sparse Package based activation e.g Share target activation or clicking on a Tile
// Launching the .exe directly will have activationArgs == null
var activationArgs = AppInstance.GetActivatedEventArgs();
if (activationArgs != null)
{
switch (activationArgs.Kind)
{
case ActivationKind.Launch:
HandleLaunch(activationArgs as LaunchActivatedEventArgs);
break;
case ActivationKind.ToastNotification:
HandleToastNotification(activationArgs as ToastNotificationActivatedEventArgs);
break;
case ActivationKind.ShareTarget: // Handle the activation as a share target
HandleShareAsync(activationArgs as ShareTargetActivatedEventArgs);
break;
default:
HandleLaunch(null);
break;
}
}
//This is a direct exe based launch e.g. double click app .exe or desktop shortcut pointing to .exe
else
{
SingleInstanceManager singleInstanceManager = new SingleInstanceManager();
singleInstanceManager.Run(cmdArgs);
}
}
Windows Share 與套件身分識別示範
下列影片示範在授與套件身分識別並註冊為共用目標之後,解除封裝的應用程式如何成為共用目標: