個人的なメモ

Tomohiro Suzuki @hiro128_777 のブログです。Microsoft MVP for Developer Technologies 2017- 本ブログと所属組織の公式見解は関係ございません。

.NET Framework から .NET 6 への移行時に便利なツール、.NET アップグレード アシスタント

目次

 
.NET Framework から .NET 6 への移行を行うときに便利なツールの一つに .NET アップグレード アシスタントがあります。
このツールを使うと、.NET Framework のソリューションを .NET 6 に変換してくれます。
 
公式ドキュメントは以下です。
docs.microsoft.com
 
 

なにができるの

主に、以下のような自動変換と、自動で変換できなかった(手作業が必要な)箇所への支援を提供してくれます。
 

自動変換

  • .NET Framework の csproj ファイル(非SDK形式)を .NET 6(SDK形式) に変換します。
  • .NET Framework から .NET 6 への移行で必ず必要になる定型的なコード変換を実施してくれます。

 

Windows アプリで .NET Framework のコードが引き続き動作するようにする支援

  • Windows 互換機能パックMicrosoft.Windows.Compatibilityパッケージが追加されることで多数のAPIセットが追加され、引き続き Windows 上でアプリを動作させる場合、既存のコードの大部分がそのまま利用できるようになります。

 

手作業が必要な箇所への支援

  • アナライザー Microsoft.DotNet.UpgradeAssistant.Extensions.Default.Analyzersパッケージが追加され、移行で問題が検出されたソースコードに警告が表示されるようになり、その後の手作業を支援してくれます。

 
支援内容の詳細は以下をご覧ください。
github.com
 
補足 1
Windows 互換機能パックは、.NET Framework のみに存在する API およびテクノロジを .NET でも利用できるようにするパッケージです。これは簡単に言えば .NET Framework の Windows 依存の API を .NET により再実装したものです。
これにより、.NET Framework のコードを .NET に移行しWindows 上で動作させる場合、既存のコードがほとんどそのままで動作します。
docs.microsoft.com
 
 

どこが便利なの

ツールで実施できる移行作業を簡単に試すことができるため、ツールでカバーできる移行がどこまでであるか、また、ツールでの変換後に必要な手作業のボリュームがどのくらいあるかを容易に確認できます。
変換の所要時間は数分から数十分程度なので、簡単に変換後に必要となる作業の量の見当をつけることができます。
 
.NET Portability Analyzer とセットで利用すると、移行計画を作成するときにとても便利です。
.NET Portability Analyzer については以下の記事を参照下さい。
hiro128.hatenablog.jp
 
 

使い方

使い方については、以下の記事を参照下さい。
hiro128.hatenablog.jp
 
 
.NET Framework から .NET 6 への移行計画については以下を参照ください。
hiro128.hatenablog.jp
 
NET Portability Analyzer については以下を参照ください。
hiro128.hatenablog.jp

 

.NET Framework から .NET 6 への移行時に便利なツール、.NET Portability Analyzer

目次

 
.NET Framework から .NET 6 への移行を行うときに便利なツールの一つに .NET Portability Analyzer があります。
このツールは、以下の2つの種類があって、使い方が少し違います。

 

 
 
公式ドキュメントは以下です。
docs.microsoft.com
 
  

なにができるの

移行先のプラットフォーム(今回なら .NET 6) で使用できない(ビルドが通らず代替が必要な) API を特定できます。
 
 

どこが便利なの

サポートされていなく手動で代替が必要な箇所を探す時に、ドキュメントを読んでサポートされていない API を手動でリストアップして、ソースコードを自分で解析するというような作業が不要で、メニューからツールを実行するだけで遅くとも数分程度でレポートを作成してくれるので、簡単に移行を実施した時に発生すると想定される作業量の見当をつけることができます。
 
このツールは移行計画を作成するときにとても便利です。
 
 

注意点

2022/02/08 現在、移行先のプラットフォームとして .NET 5 までしか対応していません。
(.NET Framework からの移行という観点では 移行先を .NET 5 に設定して利用しても実害はほとんどありません。)
 
 

使い方

Visual Studio の [ツール] -> [オプション] で設定画面が表示されるので、移行先のプラットフォームを(.NET 6 がまだないので、.NET 5)をチェックします。
f:id:hiro128:20220208163915p:plain
 
 
プロジェクトの右クリックメニューから、[Analyze Project Portability] を実行します。
f:id:hiro128:20220208164732p:plain
 
 
分析が始まります。
f:id:hiro128:20220208165134p:plain
 
 
レポートが作成されるので開いてみましょう。
f:id:hiro128:20220208165613p:plain
 
 
移植性のサマリーの値が 「98.45%」になっているので、移植できない API が含まれていることがわかります。
f:id:hiro128:20220208221750p:plain
 
 
サポートされていない API が何かを確認するには、「Details」のシートを確認するとわかります。
DataGridとそのメンバーが Not supported になっています。
f:id:hiro128:20220208222218p:plain
よって、このアプリではDataGridを .NET6で利用できる API に変更しなければいけないことがわかります。
このような手順で、サポートされていない API をリストアップすることができます。

リストアップできたら、そのAPIについて調査します。
例えばDataGridについて docs.microsoft.com でリファレンスを確認すると「代わりに DataGridViewコントロールを使用してください。」と記載されておりますので、DataGridDataGridViewに置き換えればよいことになります。
 
 

今回のサンプルコード

.NET Portability Analyzer を利用すると、このような感じでサポートされていない API を簡単にリストアップできます。
なお、今回ツールを実行したプロジェクトのサンプルコードは以下にありますので、試してみたい方は参照してみてください。
github.com
 
 
.NET Framework から .NET 6 への移行計画については以下を参照ください。
hiro128.hatenablog.jp
 
.NET アップグレード アシスタントについては以下を参照ください。
hiro128.hatenablog.jp
 
 

.NET 6 の新機能 - ランタイムのセキュリティ脆弱性の緩和策

.NET 6 の新機能 の情報の目次は以下をご覧ください。
hiro128.hatenablog.jp 
 

ランタイムのセキュリティ脆弱性の緩和策

2021年の初頭に、.NET ランタイムのセキュリティ対策のロードマップが発表されています。

これらのセキュリティ対策は単なるセキュリティパッチではなく、ランタイムの構造に手を入れる根本的な対策を含んでおり、それらは .NET 6 以降にのみ実装されることとなっています。.NET Framework のセキュリティパッチでは実装されません。
github.com
なお、.NET 6 RC 1 では、以下の2つの重要なセキュリティ対策がプレビューとなりました。なお、.NET 7ではこれらはデフォルトで有効になる予定です。
 

Hardware-enforced Stack Protection(ハードウェア強制型スタック保護)

ハードウェア強制型スタック保護は、Intel の第11世代 Tiger Lake プロセッサに および、AMD Zen 3 プロセッサに Control-flowEnforcement Technology (CET)として搭載されているセキュリティ機能です。

x64 CPU のハードウェアに依存した機能ですので当然ながら、x64 プラットフォームでのみ有効にできる機能となります。

CET はシャドウスタック(コールスタックの「影(シャドウ)」となる第2の別のスタック)を使ってすべてのリターンアドレスを記録しておく技術です。x64 のアセンブリ言語で、CALL 命令ごとにリターンアドレスがコールスタックとシャドースタックの両方にプッシュされ、RET 命令ではコールスタックとシャドースタックの両方からリターンアドレスをロードします。

2つのアドレスが一致しない場合、プロセッサは制御保護例外(#CP—Control-Protection Exception)を発行します。これがカーネルにトラップされ、セキュリティを保証するためにプロセスを終了させます。

シャドウスタックはリターンアドレスのみを格納するため、追加のメモリオーバーヘッドを最小限に抑えることができます。
 
公式情報:
CET
Understanding Hardware-enforced Stack Protection
.NET 6 compatibility with Intel CET shadow stacks (early preview on Windows) 
 
 

W^X(write xor execute:書き込みと実行の排他)

W^X は、プロセスやカーネルのアドレス空間内のすべてのページが、書き込み可能か実行可能かのいずれかであり、両方はできないというメモリ保護ポリシーです。この保護機能がないと、プログラムはデータ用のメモリ領域にCPU命令を書き込み(データ「W」として)、その命令を実行(実行可能「X」、または読み取り-実行「RX」として)することができてしまいます。

W^X は、最も単純な攻撃経路を遮断します。この機能がない場合、その他のより高度な対策はバイパスされる可能性があるため、その他の対策の意味がない結果となってしまいます。W^X を導入したことで前提条件がそろったため、今後 CET のような他の補完的な対策を追加される予定となっています。

Apple は「macOS」の将来のバージョンで W^X を必須としています。W^X は、.NET 6 を搭載したすべての OS で利用可能ですが、デフォルトで有効化されているのは、Apple Silicon 上で動く macOS のみとなっています。.NET 7 ではすべての OS で有効になる予定となっています。

公式情報:W^X
 
 

C# 10 の新機能 - const および文字列補間

C# 10 の新機能の情報の目次は以下をご覧ください。
hiro128.hatenablog.jp 
 

const および文字列補間

プレースホルダーに使用する値が定数である場合は、const で定義された値にも文字列補間に使用できるようになりました。単純にこれは便利です。

さらに、下記コード1のように補間された文字列のすべての部分が文字列リテラルであることを認識できる場合、コンパイラは、コード2のように単一の文字列リテラルとして記述されていた場合と同じように最適化して IL に出力します。つまり、以下の2つのコードはどちらの場合も、コード2のように記述されたものとして IL に出力されます。

コード1

const string Greeting = "Hello";
const string GreetingName = $"{Greeting} .NET 6"; // const で定義する値にも文字列補間が使用できる
string result = $"{GreetingName}!"; 

 
コード 2

string result = "Hello, .NET 6!";

 

導入の意図

この機能はコードの記述の自由度を高めることとコンパイラの最適化による速度向上のための機能です。
速度向上については開発者は特に意識することなく、コンパイラで最適化が働きパフォーマンスアップします。
 
公式情報:
const and interpolated strings
String Interpolation in C# 10 and .NET 6
 
 

C# 10 の新機能 - 暗黙的な using ディレクティブ

C# 10 の新機能の情報の目次は以下をご覧ください。
hiro128.hatenablog.jp 
 

暗黙的な using ディレクティブ

コンパイラによって、プロジェクトの種類ごとにあらかじめ決められたよく使われる名前空間のセットが自動的に追加されます。
例えば、コンソール アプリケーションの場合、以下の名前空間が自動的に追加されます。

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

 
.NET 5 以前のプロジェクトを .NET 6 以降に再ターゲットするときに、暗黙的な global using ディレクティブは追加されないので注意してください(場合によっては、コンパイルできなくなります)
また、.NET 6 以降の ImplicitUsings が有効になっているプロジェクトで、この機能を無効にすると、例えば、暗黙的に宣言されていた、System 名前空間が宣言されなくなってしまい、アプリがコンパイルされなくなりますので、プロジェクト単位での有効・無効の変更時はご注意ください。
 
手動で、ImplicitUsings プロパティ を true または enable に設定することで、プロジェクト単位でこの機能を有効にすることができます。
.NET 6 以降をターゲットとする C# プロジェクトのテンプレートでは、ImplicitUsings は既定で enable に設定されています。

<PropertyGroup>
  <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

 

導入の意図

明示的に指定することなくその種類のアプリで一般的によく使われる名前空間が自動的に追加されるので多くの using 行が不要になり、ソースコードからロジック以外の要素を排除できます。
こちらも「ソースコードを簡潔にするための機能」です。
 
公式情報:
Implicit usings
.NET SDK プロジェクトの MSBuild リファレンス - ImplicitUsings プロパティ