ずっと.NETframeworkを使ってました。簡単なアプリが多いのでいまでも支障はないのですが、WPFにするスキルもなくWFAを使い続けようと思っていた矢先に、.NETframeworkは長期サポート外ということが分かり、それではLTS版の.NET6にアプリを移行してみたらどうか、とやってみたらSerialPortがうまくいかないので解決するまでの覚書。
.NET アップグレード アシスタントが存在する。
永らく使ってたVisualStudio2019は.NET6.0に対応してないので、VisualStudio2022communityをあらたにインストール。
私の場合、アプリはDUTとPCは仮想シリアルでつなぐといった簡単なものが多く、アプリ規模が小さいので、だいたいは移行アシスタントで一発変換できました。
projectの.NET6への移行はWindowsのTerminal(PowerShell)で変換アプリを実行
Terminalで以下のコマンドで「.NETアップグレードアシスタント」をインストール
dotnet tool install -g upgrade-assistant
インストールできたら、目的の.slnファイルがあるフォルダに移行して、アップグレードのチェックと実行を行います。説明サイトはここ
upgrade-assistant analyze 〇〇〇.slnを実行してエラーを見ておき、
問題なければ
upgrade-assistant upgrade 〇〇〇.slnを実行する
すべて1を選択して変換終了。わたしのアプリの多くはチェック時に説明サイトと同じワーニングのほかにもう一つ、「Default font in・・・」がでています。
[11:24:18 WRN] Default font in Windows Forms has been changed from Microsoft Sans Serif to Segoe UI, in order to change the default font use the API - Application.SetDefaultFont(Font font). For more details see here - https://devblogs.microsoft.com/dotnet/whats-new-in-windows-forms-in-net-6-0-preview-5/#application-wide-default-font.
[11:24:18 WRN] HighDpiMode needs to set in Main() instead of app.config or app.manifest - Application.SetHighDpiMode(HighDpiMode.<setting>). It is recommended to use SystemAware as the HighDpiMode option for better results.
スクリーンとFont関連らしいのでとりあえずスルーして変換を実行しています。
私の作成したアプリではSerialPort以外はコンバートOK
いくつか試したアプリは大体大丈夫でした。VisualStudio2022で.NET6で問題なくコンパイル、実行、デバッグが出来ます。
SerialPortアクセスでエラーがでる。.NET6では標準で組み込まれてない
SerialPortコントロールを使ったアプリだけは、コンバートしたプロジェクトはビルドは通るのですが、実行するとSerialPortで実行エラー。
System.IO.Portsを組み込む
あまり情報がないのでChatGPTで問合せ。こんな回答です。なるほどなるほど・・・
そこから先は、わりとすらすらと解決しました。
要はツールボックスからは無くしたが、System.IO.Portsに置いてあるので、自分でコントロールを追加してくれ、ということらしい。
NuGetパッケージの管理で「System.IO.Ports」を組み込む
ツールボックスに表示されないので、これは、プロジェクト毎にやらないといけないので結構面倒ですが、いずれ.NETに復活することを期待しておきます。
パッケージの追加は何通りかあるようですが、私はソリューションエクスプローラーを右クリックして「NuGetパッケージの管理」から、System.IO.Portsを検索してインストールしました。
組み込んだ時点で、ソースファイルにusing System.IO.Ports記述が自動的に付加されました
既存の.NetframeworkのSerialPortを使ったコードに少し付けたし
名前空間、クラス宣言とインスタンス、受信イベントハンドラの記述を追加します。まずは名前空間。
using System.IO.Ports;
以下は.NETframeworkのSerialPortクラスを配置して「SerialPort1」という名前のコントロールがすでに配置してあるアプリを前提にしています。変換後も既存のSerialPort1コンポーネントが残っているのでトラブルを避けるためにも一旦削除して、残ったコードに以下を追加しました。
まず宣言。
System.IO.Ports.SerialPort serialPort1;
そのクラスのインスタンス作成時に下記を追記します。私の場合はすべてFormクラスをそのまま使うので、Formの「InitializeComponent();」行の下に追加します。
serialPort1 = new System.IO.Ports.SerialPort(new System.ComponentModel.Container());
そして、イベントハンドラの記述。
serialPort1.DataReceived += serialPort1_DataReceived;
これで、.NetFrameWorkのSerialPortクラスと同じ動作になりました。
「.NETframeworkまだ使ってんの?」なんて言われるまえに(言われない確率は高いですが・・・)対策できるとこはしておこう、という単純なことでした。