1. 程式人生 > >遷移桌面程式到MS Store(9)——APPX With Desktop Extension

遷移桌面程式到MS Store(9)——APPX With Desktop Extension

在《遷移桌面程式到MS Store(8)——通過APPX下載Win32Component》中我們討論了通過APPX來下載Service部分的安裝包。但是純UWP的客戶端並不能自動執行下載的exe或者msi檔案。本篇將著手解決這個問題。
假設我們有如下結構的application,藍色APPX中包含UWP及.NET Standard Libraries。而Service部分以WCF的形式Host在Windows Service上,這其中包含了諸如Win32 API等無法遷移到UWP的內容。

因為使用者不願除了從MS Store下載外,再額外手動下載Service部分的安裝包。所以我們希望在APPX中,包含額外的exe或msi安裝包,通過Packaging工程的形式來打包成APPX,結構圖如下所示,綠色UWP Client包含了UWP UI及.NET Standard Libraries,而Service部分直接以exe或msi形式嵌入。

樣例程式碼放在全球最大的同性交友平臺GitHub:
https://github.com/manupstairs/AppxWithDesktopExtension
也可以去MS Store試下成品:
https://www.microsoft.com/store/productid/9N22D8RLKZN2
首先看AppWithDesktopExtension1資料夾,由三個工程組成。

UWPClient是一個標準的UWP工程,該工程僅有一個Button按鈕,在點選該按鈕後,去啟動DotNetConsoleApp.exe程式。

        private async void Button_Click(object sender, RoutedEventArgs e)
        {
            if (ApiInformation.IsApiContractPresent("Windows.ApplicationModel.FullTrustAppContract", 1, 0))
            {
                await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
            }
        }

預設的UWP工程的references中是不包含ApiInformation類及FullTrustProcessLauncher類的。這裡我們需要新增Windows Desktop Extensions for the UWP的引用。

UWPClient本身並不能包含exe或者Win32App的工程,所以我們還是需要通過Packaging工程來同時包含二者。首先在AppxWithDesktopExtension工程的Applications中新增UWPClient的引用。然後再將生成好的DotNetConsoleApp.exe拷貝到AppxWithDesktopExtesion工程。假設該exe檔案是一個installer檔案,所以我們不是新增工程的reference而是直接新增該exe檔案。

這裡有個需要注意的地方是,建議建一個同名資料夾放置exe檔案。直接新增exe到根目錄的話,我在提交商店預處理的時候遇到“DotNetConsoleApp.exe“ doesn't exist in the package的錯誤,我有理由相信這是某軟對路徑的判斷沒處理好,但是咱們犟不過他,只好模仿新增工程reference的情況下的檔案結構,來繞過去這個問題。

此時該Packaging工程已同時包含UWPClient及DotNetConsoleApp.exe兩部分內容。然而實現二者之間的呼叫,我們還需要編輯Packaging工程的Package.appxmanifest檔案,選中該檔案後右鍵點選Open with…然後再彈出的對話方塊中選擇XML(Text)Editor。

在Package.appxmanifest檔案的Application節點中新增如下內容:

      <Extensions>
        <desktop:Extension
          xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
          Category="windows.fullTrustProcess"
          Executable="DotNetConsoleApp\DotNetConsoleApp.exe" />
      </Extensions>

至此,我們已基本完成了Appx with Desktop Extension的操作,幾乎已經可以使用一個很流行的詞叫“閉環”。但是等等,在點選F5執行之前,有個設定還需要改一下。在Solution檔案上右鍵選中Properties,然後在Configuration中,將Packaging工程的Platform改成和UWPClient一致。UWPClient預設是x86,當然你都改成x64也可以。

有同學肯定要問為什麼不能選AnyCPU,這是因為UWP使用了.NET Native預編譯技術,是Platform相關的,詳見:
.NET Native – What it means for Universal Windows Platform (UWP) developers
https://blogs.windows.com/buildingapps/2015/08/20/net-native-what-it-means-for-universal-windows-platform-uwp-developers/#mhT71xdPsoIclvV0.97
With .NET Native brought into the mix, AnyCPU is no longer a valid build configuration because native compilation is architecture dependent.
最後在我們執行AppxWithDesktopExtension程式之前,先看一眼DotNetConsoleApp工程到底做了什麼。

namespace DotNetConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Suppose I'm an installer.");
            Console.ReadLine();
        }
    }
}

是的,我們啥也沒做,就是列印一行字假裝我們是installer。實際在Appx我們也並沒有引用該工程,而僅是包含了事先build好的DotNetConsoleApp.exe檔案。
點選F5執行AppWithDesktopExtension工程,結果如下圖所示。

本篇內容至此結束,附上GitHub地址:
https://github.com/manupstairs/AppxWithDesktopExtension
MS Store:
https://www.microsoft.com/store/productid/9N22D8RL