­

適用於Windows桌面應用程序的.NET Core 3

  • 2019 年 11 月 7 日
  • 筆記

介紹

9月,微軟發佈了新版.NET Core,用於構建Windows桌面應用程序,包括WPF和Windows Forms。從那時起開發人員可以將傳統的nfx桌面應用程序(和控件庫)遷移到.NET Core。一般使用WPF和Windows Forms開發的業務範圍包括:

  • UI密集數據形式(FOD)應用程序
  • 響應式低延遲UI
  • 需要脫機/斷開連接運行的應用程序
  • 依賴於自定義設備驅動程序的應用程序

這只是.NET Core上Windows應用程序開發的開始。繼續閱讀以了解有關.NET Core對構建Windows應用程序更多好處的信息。


為什麼在.NET Core上使用Windows desktop?

.NET Core(以及將來在.NET Core之上構建的.NET 5)將是.NET的未來。在未來幾年內微軟將繼續支持.NET Framework,但是不會增加任何新功能,這些新功能只會添加到.NET Core(最終是.NET 5)中。為了改進Windows桌面應用領域,並使.NET桌面開發人員可以從中受益,微軟將Windows Forms和WPF引入了.NET Core,但因為與Windows API緊密相關,所以仍將僅支持Windows平台。但是.NET Core除了可以跨平台使用外,還具有許多其他功能,可以增強桌面應用程序。

首先,所有運行時改進和語言功能將僅添加到.NET Core中,以後也將添加到.NET 5中。一個很好的例子是C# 8,它已在.NET Core 3.0中可用。而且Windows Forms和WPF的.NET Core版本將成為.NET 5平台的一部分。

此外,.NET Core通過.NET Framework中不可用的新選項為應用程序帶來了部署靈活性,例如:

  • 並行部署。可以在同一台計算機上擁有多個.NET Core版本,並且可以選擇每個應用程序應針對的版本。
  • 獨立部署。可以與應用程序一起部署.NET Core平台,並完全獨立於最終用戶環境。
  • 較小的應用程序大小。在.NET Core 3中,微軟引入了一個稱為鏈接器(有時也稱為微調器)的新功能,該功能將分析代碼並將所需的程序集包括在自包含的部署中,不需要的都將被修剪掉。
  • 單個.exe文件。可以將應用程序和.NET Core平台打包在一個.exe文件中。
  • 改進了運行時性能。與.NET Framework相比,.NET Core具有許多性能優化。具體來說,在很大程度上依賴於I/O操作,網絡和數據庫操作的桌面應用程序可能會看到這些方面的性能提高。在UI渲染性能或應用程序啟動性能有一定的提示,但不是很高。

使用ReadyToRun優化.NET Core應用

通過將應用程序程序集編譯為ReadyToRun(R2R)格式,可以縮短.NET Core應用程序的啟動時間。R2R是一種提前(AOT)編譯的形式。它是.NET Core 3.0中的發佈時選擇功能。

R2R二進制文件通過減少應用程序加載時JIT需要完成的工作量來提高啟動性能。R2R二進制文件較大,因為它們既包含中間語言(IL)代碼(某些情況下仍然需要此代碼),也包含相同代碼的本機版本,以改善啟動。

要啟用ReadyToRun編譯:

  • PublishReadyToRun屬性設置為true
  • 使用顯式發佈RuntimeIdentifier

注意:編譯應用程序程序集時,生成的本機代碼特定於平台和體系結構(這就是發佈時必須指定有效的RuntimeIdentifier的原因)。

下面是一個例子:

<Project Sdk="Microsoft.NET.Sdk">    <PropertyGroup>      <OutputType>Exe</OutputType>      <TargetFramework>netcoreapp3.0</TargetFramework>      <PublishReadyToRun>true</PublishReadyToRun>    </PropertyGroup>  </Project>  

並使用以下命令發佈:

dotnet publish -r win-x64 -c Release  

注意:

  • RuntimeIdentifier可以將其設置為其他操作系統或芯片。也可以在項目文件中設置。
  • 如果在發佈過程中遇到錯誤,請添加<PublishReadyToRunShowWarnings>true</PublishReadyToRunShowWarnings> 查看詳情日誌。

Assembly linking

.NET core 3.0 SDK附帶了一個工具,該工具可以通過分析IL和修剪未使用的程序集來減小應用程序的大小。這是.NET Core 3.0中的另一個發佈時選擇加入功能。

藉助.NET Core,始終可以發佈包含運行代碼所需的一切的自包含應用程序,而無需在部署目標上安裝.NET。在某些情況下,該應用僅需要框架的一小部分即可運行,並且可能僅包含所使用的庫就可以變得更小。

使用IL鏈接器掃描應用程序的IL,以檢測實際需要哪些代碼,然後修剪未使用的框架庫。這可以大大減小某些應用程序的大小。通常,類似小型工具的控制台應用程序受益最大,因為它們傾向於使用框架的較小子集,並且通常更易於調整。

要使用鏈接器:

  • PublishTrimmed屬性設置為true
  • 使用顯式發佈RuntimeIdentifier

下面是一個例子:

<Project Sdk="Microsoft.NET.Sdk">    <PropertyGroup>      <OutputType>Exe</OutputType>      <TargetFramework>netcoreapp3.0</TargetFramework>      <PublishTrimmed>true</PublishTrimmed>    </PropertyGroup>  </Project>  

並使用以下命令發佈:

dotnet publish -r win-x64 -c Release

注意:RuntimeIdentifier可以將其設置為其他操作系統或芯片。也可以在項目文件中設置。

經測試對於helloworld應用程序,大小從〜68MB減小到〜28MB。

修剪後使用反射或相關動態功能的應用程序或框架(包括ASP.NET Core和WPF)通常會中斷,因為鏈接器不了解這種動態行為,並且通常無法確定反射所需的框架類型在運行時。要修剪此類應用程序,您需要告知鏈接器有關代碼中以及依賴的任何包或框架中反射所需要的任何類型。修剪後一定要測試應用程序。針對這個問題微軟在.NET 5上正在努力改善。

有關IL Linker的更多信息,請參閱文檔,或訪問mono / linker存儲庫。

注意:在.NET Core的早期版本中,ILLink.Tasks作為外部NuGet軟件包提供,並提供了許多相同的功能。請更新到.NET Core 3.0 SDK,然後嘗試新的體驗!

Assembly linking和ReadyToRun compiler可用於同一應用程序。通常,Assembly linking使應用程序更小,ready-to-run compiler 使應用程序更大一些,但在性能上有明顯優勢。可以在各種配置中進行測試以了解每個選項的影響。

發佈單文件可執行文件

可以使用發佈單個文件的可執行文件dotnet publish。這種形式的單個EXE實際上是一個自解壓縮的可執行文件。它包含所有依賴項(包括本地依賴項)作為資源。在第一次啟動時,它將所有依賴項複製到一個臨時目錄,並在該目錄中加載它們。它只需要解壓縮依賴項一次。當再次啟動時將會很快啟動,並且沒有任何損失。

可以通過將PublishSingleFile屬性添加到項目文件或在命令行上添加新的參數來啟用此發佈選項。

要生成一個獨立的單個EXE應用程序,在這種情況下,對於64位Windows:

dotnet publish -r win10-x64 /p:PublishSingleFile=true

注意:

  • RuntimeIdentifier可以將其設置為其他操作系統或芯片。也可以在項目文件中設置。
  • 關於臨時目錄,請參考Extracting Bundled Files to Disk

有關更多信息,請參見單文件捆綁器

Assembly trimmer, ahead-of-time compilation(通過crossgen)和單個文件捆綁都是.NET Core 3.0中的所有新功能,可以一起使用,也可以單獨使用。

綜合使用

通過設置屬性<PublishSingleFile><RuntimeIdentifier><PublishTrimmed><PublishReadyToRun><PublishReadyToRunShowWarnings>在發佈配置文件中,能夠將修剪、ahead-of-time compilation後的自包含應用程序部署為單個.exe文件,如下面的示例所示。

<PropertyGroup>      <OutputType>Exe</OutputType>      <TargetFramework>netcoreapp3.0</TargetFramework>      <PublishSingleFile>true</PublishSingleFile>      <RuntimeIdentifier>win-x64</RuntimeIdentifier>      <PublishReadyToRun>true</PublishReadyToRun>      <PublishReadyToRunShowWarnings>true</PublishReadyToRunShowWarnings>      <PublishTrimmed>true</PublishTrimmed>  </PropertyGroup>  

然後使用Visual Studio發佈工具或者命令dotnet publish -c release發佈。

MSIX

如果你正在尋找一種將應用程序分發給最終用戶的方法,那麼將其打包為MSIX可能比創建單個.exe文件更好。PublishSingleFile提供了一個包含所有應用程序依賴項的自解壓ZIP文件,而MSIX提供了乾淨可靠的Windows集成應用程序安裝和卸載。《MSDN雜誌》上寫了一篇文章,不僅展示了如何打包應用程序,而且還展示了如何為MSIX包設置持續集成(CI),持續部署(CD)和自動更新。


.NET Framework desktop 和.NET Core desktop 之間的區別

WPF應用程序在.NET Core上完全受支持。對於Windows Forms,運行時部分已完全移植到.NET Core,並且微軟團隊正在繼續開發Windows窗體設計器。微軟計劃在2020年第四季度之前將其準備就緒,現在可以在Visual Studio預覽下載頁面 16.4 Preview 3或更高版本中籤出設計器的Preview版本。別忘了在工具->選項->預覽功能->使用.NET Core應用程序的Windows窗體設計器預覽,然後重新啟動Visual Studio

重大變化

.NET Framework和.NET Core之間有一些重大更改,但與Windows窗體和WPF區域相關的大多數代碼都按原樣移植到了Core。如果使用的組件包括WCF客戶端,代碼訪問安全性,應用程序域,互操作性和遠程處理,則要切換到.NET Core,則需要重構代碼。

請記住另一件事,.NET Core上的默認輸出路徑與.NET Framework上的默認輸出路徑不同,因此,如果在代碼中對正在運行的應用程序的文件/文件夾結構進行了一些假設,則它可能會在運行時失敗。

此外,配置.NET功能的方式也有所變化。.NET Core而非machine.config文件使用的<something>.runtimeconfig.json是應用程序隨附的文件,該文件具有相同的通用目的和相似的信息。一些配置,如system.diagnosticssystem.netsystem.servicemodel不被支持,那麼應用程序配置文件將失敗是否含有這些內容的加載。此更改影響System.Diagnostics以前使用XML配置通常配置的跟蹤和WCF客戶端方案。在.NET Core中,需要改為在代碼中進行配置。要更改行為而無需重新編譯,請考慮使用從Microsoft.Extensions.Configuration源或從中加載的值來設置跟蹤和WCF類型appSettings

可以在.NET Core無法使用的.NET Framework技術找到有關.NET Core和.NET Framework之間差異的更多信息。


從.NET Framework移植到.NET Core

首先,運行可移植性分析器並在需要時更新代碼以與.NET Core 100%兼容。這是有關使用可移植性分析器的說明。建議在對應用程序進行任何更改之前使用源代碼控制或備份代碼,以防重構無法按照希望的方式進行。

當應用程序與.NET Core完全兼容時,就可以準備移植它了。首先,可以嘗試使用工具try-convert以幫助將.NET Framework項目自動轉換為.NET Core。

此工具只是通往.NET Core的起點。它也不是受支持的Microsoft產品。儘管它可以幫助解決遷移的某些機械問題,但它不能處理所有方案或項目類型。如果遇到該工具無法轉換的項目,則必須手動進行移植。

關於.Net Core3.1的支持

.NET Core 3.1是一個小型且簡短的發行版,着重於Blazor和Windows桌面應用(.NET Core 3.0的兩個重大改進)的關鍵改進。這將是一個長期支持(LTS)版本,至少支持3年,預計最終發佈日期為2019年12月。
此版本中最大的改進是對C++/CLI(又稱為「託管C++」)的支持