把既有的 WPF 或 Win32 程式封裝成 *.appx 放到 Store 有什麽好處?
- 讓既有程式可以操作 Windows Universal Platform (UWP) APIs;可參考 WPF 使用 Windows 10 APIs - 1, 2 與 3 的介紹;
- 方便的部署,搭配 Store 收集用戶的 review, 下載數, crashes 等;
- ... 還有很多這裏就不多做說明;
在 Package desktop applications (Desktop Bridge) 提供多種方式:
- Build an MSIX from an existing app installer利用 MSIX Packaging Tool 或 Desktop App Converter 要注意兩者工具支援封裝與被安裝時要求的 Windows 10 版本有所不同。
- Build an MSIX from source code using Visual Studio在既有的方案加入 Windows Application Package Project 並把 desktop project 加入其中就可以進行封裝與除錯。
這是最簡單的方式,但如果 desktop project 有特殊的流程,例如: 建置出來的 *.dll 要混肴或是 sign 憑證,建議在 desktop project 加入 PostBuildEvent 做處理並輸出到 Windows Application Package Project 中。
不然會遇到 How to package a WPF app with post build dependencies into UWP package? 的問題。 - Third-party installers可參考 Package a desktop application using third-party installers 介紹的第三方工具來執行,相對的有些要收費。
- Manual packaging利用 MakeAppx.exe 來封裝 Windows app package。可參考 Package a desktop application manually。
利用 Package a desktop application manually 介紹怎麽手動封裝成 *.appx;
- 建立 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:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" IgnorableNamespaces="uap rescap"> <!-- Identify 的參數可到 Partner Center 中產品的 Product identify 取得; ProcessorArchitecture 根據您預設支援的平臺設定; --> <Identity Name="{Package/Identity/Name}" Publisher="{Package/Identity/Publisher}" Version="9.9.9.9" ProcessorArchitecture="x86" /> <Properties> <DisplayName>WPFWindows</DisplayName> <PublisherDisplayName>{Package/Properties/PublisherDisplayName}</PublisherDisplayName> <Logo>AppIcon\StoreLogo.png</Logo> </Properties> <Dependencies> <!-- 要設定 Windows.Desktop 因爲其他設備不支援 --> <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.16299.0" MaxVersionTested="10.0.18362.0" /> </Dependencies> <Resources> <Resource Language="en"/> <Resource Language="ja"/> <Resource Language="zh-Hans"/> <Resource Language="zh-Hant"/> </Resources> <Applications> <Application Id="App" Executable="WPFWindows.exe" EntryPoint="Windows.FullTrustApplication"> <uap:VisualElements DisplayName="WPFWindows" Description="WPFWindows" BackgroundColor="#00AED8" Square150x150Logo="AppIcon\Square150x150Logo.png" Square44x44Logo="AppIcon\Square44x44Logo.png"> <uap:DefaultTile Wide310x150Logo="AppIcon\Wide310x150Logo.png" /> <uap:SplashScreen Image="AppIcon\SplashScreen.png" /> </uap:VisualElements> </Application> </Applications> <Capabilities> <Capability Name="internetClient" /> <rescap:Capability Name="runFullTrust" /> </Capabilities> </Package>
- 根據您在 Partner Center 注冊的 product 填入它所屬 product identify 中必要的參數:
- Package/Identity/Name
- Package/Identity/Publisher
- Package/Properties/PublisherDisplayName
- <Resources /> 記得填入 app 支援的多個語言包或是多個 scale(100,125,150,200,400) 的 app icon;
- <Application /> 的 EntryPoint="Windows.FullTrustApplication" 是固定的;Executable="WPFWindows.exe" 則設定 WPF 的執行檔;如果您使用 Windows Application Package Project 方式,它在 obj/release/packagelayout 會要產生一樣的内容;
- <Capabilities/> 記得宣告 <rescap:Capability Name="runFullTrust" />;
- 根據您在 Partner Center 注冊的 product 填入它所屬 product identify 中必要的參數:
- 準備 appx 需要的 Store logo因爲 appxmanifest.xml 從的 tag 寫了這些圖示的 icon,每一張圖要分別準備 scale-100, scale-125, scale-150, scale-200 與 scale-400 五種尺寸。例如:把產生的 app icons 放在一個目錄 AppIcon。
詳細可參考 App icons and logos 的介紹或是搭配 UWP Tile Generator Extension for Visual Studio 產生圖示; - 利用 MakePri.exe 建立必要的 priconfig.xml 與多個 resources.pri參考 Generate a Package Resource Index (PRI) file 介紹,App 要支援多語系跟多種 scale 圖示時需要將它們分別建立出來,所以先建立 priconfig.xml 定義需要的内容,才能建立相對應的 resources.dll。
步驟:
- 假設 WPF 專案的位置在 c:\sources\WPFWindows\bin,那產生的 priconfig.xml 要放在 *.exe 的相同目錄;
- 把上一步產生的 AppIcon 目錄放到跟 *.exe 相同的目錄;
- 執行指令 makepri.exe createconfig /pr $srcPath /cf $srcPath\priconfig.xml /dq en-US /o
makepri.exe 位置在 C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64 其中 10.0.18362.0 根據您安裝的 Windows 10 SDK 來更換,後面介紹的 makeappx.exe 與 signtool.exe 也在相同的目錄裏面。
$srcPath 換成專案 *.exe 的路徑。 - 執行指令 makepri.exe new /pr $srcPath /cf $srcPath\priconfig.xml /o如果發現 resources.dll 等多個檔案(根據支援的語系跟 scales) 不在 *.exe 同一個目錄,要記得複製進去。或者,在執行指令前先把 terminal 指定到 *.exe 相同的路徑再執行指令;
原因 makepri.exe new 指令中只能有一個輸出檔案 /of C:\MyApp\src\resources.pri,但是因爲我們需要多個 resources.dll 才會需要先進入該路徑;
- 利用 MakeAppx.exe 封裝既有 desktop project 編譯出來的 *.exe 或 *.dll 變成 *.appx
執行指令 MakeAppx.exe pack /v /h sha256 /d $srcPath /p $appxFile。
$appxFile 換成輸出的目錄,例如:c:\appx\WPFWindows.appx;
這樣就完成了封裝的任務,但是它還無法被人點擊 *.appx 直接安裝,因爲少了憑證的認證。 - 利用 SignTool.exe 搭配 *.pfx 或是 *.cer 為 *.appx 加入憑證如果您沒有 Store 專用的 pfx, 可以參考 Create a certificate for package signing 的介紹,建立一個憑證。該憑證需要 identify 等資料(同寫在 appxmanifest.xml 裏的内容),我建議您可以產生一個時間比較長效的,避免每一年需要產生一次。
產生好 *.pfx 之後,把檔案放到 *.exe 來方便執行 SignTool.exe sign /fd SHA256 /a /f $pfxFile $appxFile。
$pfxFile 換成您建立的 *.pfx 檔案。這樣才能點擊 *.appx 來安裝;
[注意]
由於憑證是自己建立的,如果您直接把 *.appx 交給其他電腦安裝會遇到憑證不受信任的錯誤而無法安裝,可以參考下面的指令建立成 *.bat,並把它與 *.appx 與 *.pfx 同一個目錄,點擊它來完整第一次的憑證安裝:
@echo off pushd "%CD%" if not "%1"=="am_admin" (powershell start -verb runas '%0' am_admin & exit /b) CD /D "%~dp0" echo %cd% echo "install certification ..." // myApp_StoreKey.pfx 要換成您建立的憑證名稱 Powershell.exe Import-PfxCertificate -FilePath myApp_StoreKey.pfx -CertStoreLocation Cert:\LocalMachine\Root echo "install msix ..." Powershell.exe Add-AppxPackage -path .\*.appx pause
- 如果要包裝成 *.appxbundle:完成 *.appx 的 sign 之後,再利用 MakeAppx.exe 換成封裝成 *.appxbundle 最後再對 *.appxbundle 做 sign。
步驟:
- 建立一個目錄 package,放在 *.exe 目錄的上一層或是任何地方;
- 修改建立 *.appx 時的輸出目錄到 package 目錄
- 讓 terminal 到 package 目錄再執行 MakeAppx.exe bundle /bv $appxVersion /d $bundlePath /p $appxBundleFile。$appxVersion 換成需要的版本號,$bundlePath 則是把 *.appxbundle 放到 package 目錄,更多 bundle 説明可參考 Create an app bundle。
- 再 sign 一次:SignTool.exe sign /fd SHA256 /a /f $pfxFile $appxBundleFile
完成上面的步驟就大功告成了。
您可以直接上傳 *.appxbundle 到 partner 或是交給 Partner Center 來上架。
完整版的指令如下(以 powershell 來做範例):
$projectFolder = 'WPFWindows'
$srcFolder = '$projectFolder\src'
$setupBundleFolder = '$projectFolder \package'
$appxVersion = '10.0.0.0'
# 建立 appx 與 appxbundle
Write-Host '1. copy appxManifest.xml and AppIcon into srcFolder'
Copy-Item -Path $projectFolder\AppIcon -Destination $srcFolder -force -recurse
Copy-Item -Path $projectFolder\appxManifest.xml -Destination $srcFolder -force -recurse
Write-Host '2. create mutiple resources, msix file and sign it'
$sdkPath = "C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64";
$makePri = "${sdkPath}\makepri.exe"
$makeAppx = "${sdkPath}\MakeAppx.exe"
$signTool = "${sdkPath}\SignTool.exe"
$srcPath = "${currentPath}\${srcFolder}"
$bundlePath = "${currentPath}\${setupBundleFolder}"
$appxPath = "${bundlePath}\WPFWindows_${appxVersion}_x86"
$appxFile = "${appxPath}.appx"
$appxBundleFile = "${appxPath}.appxbundle"
$pfxFile = "${currentPath}\${projectFolder}\myApp_StoreKey.pfx"
& $makePri createconfig /pr $srcPath /cf $srcPath\priconfig.xml /dq en-US /o
& cd $srcPath
& $makePri new /pr $srcPath /cf $srcPath\priconfig.xml /o
& cd ../../../
& $makeAppx pack /v /h sha256 /d $srcPath /p $appxFile
& $signTool sign /fd SHA256 /a /f $pfxFile $appxFile
& $makeAppx bundle /bv $appxVersion /d $bundlePath /p $appxBundleFile
& $signTool sign /fd SHA256 /a /f $pfxFile $appxBundleFile
最後建立好 *.appx 或是 *.appxbundle 時,要記得做 Windows Desktop Bridge app tests。======
這篇把根據微軟的教學補充上我自己踩過的雷,因爲建立好的 *.msix 或 *.appx 竟然在送到 Store 審核時檢查的條件不同,所以去看了 Supported OS versions for installed packages 才知道兩者在 Windows 10 版本的要求有不同。
希望對大家有幫助,謝謝。
References:
- An easier way to generate the packages for a Desktop Bridge converted app
- Package a .NET desktop application using the Desktop Bridge and Visual Studio Preview
- Sign an app package using SignTool
- Create an app package with the MakeAppx.exe tool
- Package a desktop app manually
- How to use the Desktop Bridge to create an appx package for XAF
- Package a desktop app from source code using Visual Studio
- MSIX Packaging SDK
- MSIX: Inside and Out : Build 2018
- Package an app by using Visual Studio (Desktop Bridge)
- A list of all
tags that ship with MSBuild / Visual Studio - Create an app package with the MakeAppx.exe tool
- Introducing .NET Core Windows Forms Designer Preview 1
- Build resources into your app package, instead of into a resource pack
- Start a Win32 process from a Universal Windows Platform (UWP) app
沒有留言:
張貼留言