-
Notifications
You must be signed in to change notification settings - Fork 0
MS_MigrationToWindowsDesktopPacks
- 戻る(.NET Coreへの移行)
.NET Core 3.0(.NET Core を参照)から、
Windows Forms / WPF のサポートが追加された。
基本的にポーティング移行になるもよう(VS2019 ではデザイナ使用不可)。
補足(デザイナは VS2019 の途中で使えるようになった): 本ページ執筆時点の
「VS2019 ではデザイナ使用不可」は当時として正しいが、その後解消された。【デザイナ対応の経緯】★ ・.NET Core 3.0 リリース時(2019年9月) → WPF / Windows Forms とも 【デザイナが未提供】 → .NET Framework 側のプロジェクトで デザインし、ファイルをリンクする (本ページの手順)という回避策が必要だった ・WPF デザイナ → VS 2019 16.3 頃から【正式提供】 ・Windows Forms デザイナ → プレビューを経て 【VS 2019 16.10(2021年5月)で正式提供】★ → 出遅れた理由は、 デザイナがコントロールを 【実際にインスタンス化して表示する】仕組みのため、 .NET Framework 上の VS から .NET Core のコントロールを 読み込む【プロセス分離の仕組み】を 作り直す必要があったから ・現在(VS 2022 / .NET 8, 9) → 【両方とも普通に使える】★ → 【今から移行するなら、本ページの 「ファイルをリンクする」手順は不要】である。 ただし、大規模プロジェクトを 段階的に移行する際の手法としては 今も有効なので、記録として価値がある ★
- ...の準備(既存)
- ...の移行性評価(後述の「アナライザー」を参照)
-
...の準備(新規)
- ...の生成
- ...の設定
- ...から、.NET Framework 版プロジェクトのソース・ファイルをリンクする。
-
...のコンパイルを通す。
- ...へ、NuGet パッケージを追加
- ...へ、必要に応じて後述の互換機能パックを追加
- ...その他、非互換の API などの置換などを行う。
-
...のビルドと実行とテストの実施
- VS2019 では、
- .NET Core のデザイナは提供されない。
- .NET Framework のデザイナを使用する。
.NETのクロスプラットフォーム対応 の該当節を参照。
補足(現在の移行支援ツール): 「アナライザー」として本ページが指すのは
.NET Portability Analyzer と思われる。現在は後継がある。【移行支援ツールの変遷】★ ・【.NET Portability Analyzer】(旧) → API の移植可能性をレポート → 現在は【非推奨】。リポジトリはアーカイブ ・【.NET Upgrade Assistant】★(現行) → CLI / Visual Studio 拡張の両方 → プロジェクト形式の変換(SDK スタイル化)、 TargetFramework の変更、 NuGet 参照の付け替えまで【自動でやる】 dotnet tool install -g upgrade-assistant upgrade-assistant upgrade <path> ・【.NET API アナライザー】 → コンパイル時に 非互換 API・非推奨 API を警告する (Microsoft.DotNet.ApiCompat 等) ・【try-convert】 → 旧形式 .csproj → SDK スタイルへの変換 → Upgrade Assistant が内部で使う → 【まず Upgrade Assistant を掛ける】のが 現在の定石。本ページの手作業の大半が自動化される ★
- Windows 専用 API やプラットフォーム非依存 API など、約 20,000 の API を提供
- NuGet パッケージ
Microsoft.Windows.Compatibility経由で提供される。 - .NET Core または .NET Standard を対象とするプロジェクトから参照できる。
| # | 分類 | 提供される領域 |
|---|---|---|
| 1 | .NET Framework | CodeDom |
| 2 | .NET Framework | System.Runtime.Caching |
| 3 | .NET Framework | Windows Workflow Foundation (WF) |
| 4 | .NET Framework | Windows Communication Foundation (WCF) |
| 5 | .NET Framework | Managed Extensibility Framework (MEF) |
| 6 | .NET Framework | 互換性(Microsoft.Windows.Compatibility.Shims) |
| 7 | Windows | Codepage |
| 8 | Windows | GDI+ |
| 9 | Windows | ODBC |
| 10 | Windows | Registry |
| 11 | Windows | Service |
| 12 | Windows | 暗号化 |
| 13 | Windows | EventLog |
| 14 | Windows | アクセス制御リスト (ACL) |
| 15 | Windows | パフォーマンス カウンター |
| 16 | Windows | WMI (Windows Management Instrumentation) |
| 17 | Windows | Active Directory(X.500) |
移行メモ(体裁): 2 階層の箇条書きを表に整理した。
補足(互換機能パックの注意点): 便利だが、入れれば済むものではない。
【① 参照した時点で Windows 依存になる】★ Microsoft.Windows.Compatibility は 【Windows 専用 API を含む】 → 参照すると 「クロスプラットフォーム化」の目的からは遠ざかる → CA1416(プラットフォーム互換性アナライザー)が 警告を出すようになった(.NET 5 以降)★ → 「まず動かす」ための足場と割り切り、 【段階的に外していく】のが正しい使い方 【② 入っていても "動かない" ものがある】★ ・【WCF はサーバー側が入っていない】 → クライアント(System.ServiceModel.*)のみ → サーバーは【CoreWCF】(コミュニティ移植)を使う ・【WF も同様】 → CoreWF を使う ・System.Drawing.Common(GDI+)は → .NET 6 で【Windows 以外がサポート外】に → .NET 7 で【非 Windows は例外を投げる】★ → クロスプラットフォームなら ImageSharp / SkiaSharp へ移行する 【③ 個別パッケージで足りることが多い】 Microsoft.Windows.Compatibility は 【巨大なメタパッケージ】 → Registry だけ要るなら Microsoft.Win32.Registry だけ入れる方がよい ★
Open棟梁Project での事例
- Support to Windows Forms/WPF
by “Windows Desktop Packs” on NET Core 3.0.
· Issue #328 · OpenTouryoProject/OpenTouryo
https://github.com/OpenTouryoProject/OpenTouryo/issues/328
新規作成 → プロジェクトで取得できる。
-
Windows Forms の場合
...のプロジェクト・ファイルの雛形
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon />
<StartupObject />
</PropertyGroup>
</Project>-
WPF の場合
...のプロジェクト・ファイルの雛形
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
</Project>補足(現在の書き方:
WindowsDesktopSDK は不要): .NET 5 以降、
プロジェクト ファイルの書き方が簡素化された。<!-- .NET 5 以降(現在の書き方)★ --> <Project Sdk="Microsoft.NET.Sdk"> <!-- ← 通常の SDK でよい --> <PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net8.0-windows</TargetFramework> <!-- ★ --> <UseWindowsForms>true</UseWindowsForms> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> </PropertyGroup> </Project>【変わった点】★ ① SDK は【Microsoft.NET.Sdk】に統一 → Microsoft.NET.Sdk.WindowsDesktop は 【互換のため残っているが、使う必要はない】 ② TargetFramework に【-windows】を付ける → net8.0-windows → さらに OS バージョンも指定できる net8.0-windows10.0.19041.0 (WinRT API を使う場合に必要)★ ③ UseWindowsForms / UseWPF は【そのまま】 → 両方 true にすれば併用も可能
-
上記のプロジェクト・ファイルにファイルをリンクする。
-
.NET Framework のプロジェクト・ファイルと同じフォルダ階層に、
.NET Core のプロジェクト・ファイルを配置してしまっても行ける。
補足(なぜ「同じ階層に置けば行ける」のか): SDK スタイルの
プロジェクトの既定の挙動による。【SDK スタイル プロジェクトの既定】★ ・プロジェクト ファイルのあるフォルダ配下の 【*.cs を自動的に全部含める】 (旧形式は 1 つずつ <Compile Include> が必要だった) → だから「同じ階層に .csproj を置くだけ」で ソースが拾われる ★ 【明示的にリンクする場合】 <ItemGroup> <Compile Include="..\OldProj\**\*.cs" Exclude="..\OldProj\obj\**;..\OldProj\bin\**" Link="%(RecursiveDir)%(Filename)%(Extension)" /> </ItemGroup> ※ obj / bin の除外を忘れると 【自動生成ファイルまで拾って壊れる】★ 【注意】 ・同じ階層に置くと 【obj / bin が衝突する】 → BaseIntermediateOutputPath / BaseOutputPath を 分けておくと安全 ★ ・両方のプロジェクトを同時にビルドすると ファイル ロックが起きることがある
以下のポイントに注意しながらポーティング移行を行う。
-
AssemblyInfo.cs は除外(削除)する。
-
プロジェクト・ファイルを修正する。
-
ルート名前空間
-
アセンブリ名
-
プロジェクト出力
-
参照設定や NuGet 参照
-
ファイル
- ビルド アクションの設定
- Resource ファイルの再構成
-
-
NuGet 周り
- 参照アセンブリ(DLL)を吸わなくなったので、個別に NuGet 参照。
- 必要に応じて、NuGet パッケージの依存関係の設定を適正化する。
-
#IF用に NETCOREAPP を追加- 既定で、NETCOREAPP_3_0 があるのでこちらを利用してもイイ。
- 必要に応じて、
#IF-#ELSEの条件付きコンパイルディレクティブを実装する。
移行メモ(正誤): 移行元では条件付きコンパイル シンボルが
「NETCOREAPP_3_0」と記載されていたが、
正しくはNETCOREAPP3_0(NETCOREAPPの直後にアンダースコアは入らない)である。
なお#IFは VB の記法で、C# では#ifである。
補足(
AssemblyInfo.csを削除する理由と、残したい場合):
単に「不要になった」のではなく、衝突するから削除するのである。【SDK スタイルでは属性が自動生成される】★ obj\Debug\net8.0-windows\ XXX.AssemblyInfo.cs ← 【ビルド時に自動生成される】 → AssemblyVersion / AssemblyTitle / AssemblyCompany 等 → 手書きの AssemblyInfo.cs を残すと 【CS0579 "重複する属性" エラー】になる ★ 【値はプロジェクト ファイルで指定する】 <PropertyGroup> <AssemblyVersion>1.0.0.0</AssemblyVersion> <FileVersion>1.0.0.0</FileVersion> <Version>1.0.0</Version> <Company>...</Company> <Product>...</Product> </PropertyGroup> 【どうしても手書きを残したい場合】 <GenerateAssemblyInfo>false</GenerateAssemblyInfo> → 自動生成を止める → InternalsVisibleTo など 属性を細かく制御したい場合に使う ★【条件付きコンパイル シンボルの既定値】★ net8.0-windows なら自動的に定義される NET / NET8_0 / NET8_0_OR_GREATER NET5_0_OR_GREATER … NET7_0_OR_GREATER NETCOREAPP / NETCOREAPP3_1_OR_GREATER WINDOWS / WINDOWS8_0_OR_GREATER … → 【_OR_GREATER 系を使う】のが定石 ★ #if NET5_0_OR_GREATER // 新しい実装 #else // .NET Framework 向け #endif → バージョンを上げるたびに 条件を書き換えなくて済む
- OutputType を WinExe から Library へ変更する。
<OutputType>Library</OutputType>- Windows Forms / WPF のサポートの両方に対応する場合、以下を併記
<UseWindowsForms>true</UseWindowsForms>
<UseWPF>true</UseWPF>- Sgen.exe(XmlSerializer 専用コンパイラ)の問題で、
GenerateSerializationAssemblies : Off を追記した。
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>補足(
Sgen.exeの問題とは何だったか): この対処の背景を補っておく。【Sgen.exe(XML シリアライザー ジェネレーター)】★ XmlSerializer は既定で 【実行時に動的にアセンブリを生成する】 → 初回の生成コストが大きい → これを【ビルド時に事前生成】するのが Sgen.exe (XXX.XmlSerializers.dll ができる) ・.NET Framework 時代のツールであり、 【.NET Core では動かない / 不要】★ → OutputType が Library だと 既定で走ろうとしてエラーになるケースがあった → Off にして回避する(本ページの対処) 【現在】 ・.NET Core / .NET 5+ では Microsoft.XmlSerializer.Generator という 別ツールが用意されたが、 【必要なケースは限られる】 ・そもそも → 新規なら【System.Text.Json】★ → XML が必須なら XmlSerializer をそのまま使い、 インスタンスを【静的にキャッシュする】 (毎回 new すると都度アセンブリ生成が走る)★
設定ファイル
- app.config を除外(削除)し、appsettings.json を追加。
- Microsoft.Extensions.Configuration.XXX 周辺の参照を追加
- 冒頭で、appsettings.json の初期化コードを実行
補足(
app.configは「使えなくはない」): 本ページの手順は
推奨される移行先だが、経緯を補っておく。【app.config の扱い】★ ・.NET Core でも 【System.Configuration.ConfigurationManager】を NuGet で入れれば app.config は読める → 【段階移行の足場としては有効】 ・ただし - configSections を使った独自セクションは 動かないことがある - 暗号化(aspnet_regiis)は使えない - ConnectionStrings 以外は 新しい仕組みと二重管理になる 【推奨される移行先】 appsettings.json + 【Microsoft.Extensions.Configuration】★ var config = new ConfigurationBuilder() .SetBasePath(AppContext.BaseDirectory) // ★ .AddJsonFile("appsettings.json", optional: false) .AddJsonFile($"appsettings.{env}.json", optional: true) .AddEnvironmentVariables() .AddUserSecrets<Program>() // 開発時のみ .Build(); → 環境ごとの上書き、環境変数、 シークレット管理が【階層的に合成される】★【SetBasePath に AppContext.BaseDirectory を使う理由】★ 後述の「実行ファイルのパスに注意」(しばやん氏の記事)と 同じ話。 ・Directory.GetCurrentDirectory() は 【カレント ディレクトリ】であり、 exe の場所とは限らない (ショートカット起動、タスク スケジューラ起動で変わる) ・Assembly.Location は 【単一ファイル発行だと空文字】になる ★ → 【AppContext.BaseDirectory】が最も安全
-
.NET Core でのサポートは予定されていない模様。
-
→ .NET 5 でサポートされる模様。
-
参考
- Will ClickOnce be ported to .NET Core 3 as well as WinForms - Stack Overflow
https://stackoverflow.com/questions/56390876/will-clickonce-be-ported-to-net-core-3-as-well-as-winforms - 「ClickOnce」インストールが「.NET Core」に対応 ~「.NET 5.0」リリース候補2版 - 窓の杜
https://forest.watch.impress.co.jp/docs/news/1283252.html
- Will ClickOnce be ported to .NET Core 3 as well as WinForms - Stack Overflow
補足(ClickOnce は .NET 5 以降で正式にサポートされた): 本ページの
「→ .NET 5 でサポートされる模様」はそのとおりになった。【現在の状況】★ ・【.NET 5 以降の Windows デスクトップ アプリで ClickOnce 発行が可能】 ・Visual Studio の [発行] ウィザードから選べる ・CLI からも可能 dotnet publish -p:PublishProfile=ClickOnceProfile 【制約】 ・【Windows 専用】(当然) ・self-contained 発行との組み合わせに制限がある ・単一ファイル発行とは併用しにくい 【配布方式の選択肢(現在)】★ ・【ClickOnce】 … 自動更新が要る社内アプリ。実績豊富 ・【MSIX】★ … Microsoft の推奨。 クリーンなインストール/アンインストール、 Store 配布、増分更新 → ただし【署名証明書が必須】で 社内配布のハードルが高い ・【自己完結型発行 + zip 配布】 … .NET ランタイムを同梱するので 「入っていない」問題が起きない ★ → 更新は自前 or Squirrel / Velopack ・MSI(WiX 等) … 従来型。GPO 配布と相性がよい
現状では、VB 版テンプレート(dotnetコマンド を参照)が存在しない。
補足(VB のテンプレートは提供された): これもその後解消された。
【現在】★ dotnet new winforms -lang VB dotnet new wpf -lang VB → 【VB でも Windows Forms / WPF の .NET プロジェクトを作れる】 【VB の現在の立ち位置】 ・2020年、Microsoft は 「VB に【新しい言語機能は追加しない】」と表明 ★ → ただし【サポートは継続】する → .NET 8 / 9 でも VB の Windows Forms は動く ・対象ワークロード → Windows Forms / WPF / コンソール / クラス ライブラリは【対応】 → ASP.NET Core は【非対応】★ → 既存 VB 資産の維持には十分だが、 新規は C# を選ぶのが順当
-
MicrosoftがWPF、WinForms、WinUIをオープンソース化
https://www.infoq.com/jp/news/2018/12/msft-open-source-wpf-winforms -
.NET Core 3 で Windows デスクトップアプリケーションをサポートするみたい
(.NET Core 3 and Support for Windows Desktop Applications) - いろいろ備忘録日記
https://devlights.hatenablog.com/entry/2018/05/08/120953 -
Windows Compatibility Pack for .NET Core:Dev Basics/Keyword - @IT
https://www.atmarkit.co.jp/ait/articles/1711/21/news024.html
- .NET Core 3 and Support for Windows Desktop Applications
https://devblogs.microsoft.com/dotnet/net-core-3-and-support-for-windows-desktop-applications/ - Announcing .NET Core 3 Preview 1 and Open Sourcing Windows Desktop Frameworks
https://devblogs.microsoft.com/dotnet/announcing-net-core-3-preview-1-and-open-sourcing-windows-desktop-frameworks/
-
WPF on .NET Coreをやってみる(プレビュー版) - Qiita
https://qiita.com/soi/items/e1cf2abf9845164bf439 -
.NET Core 3.0 でのデスクトップ開発 - かずきのBlog@hatena
https://blog.okazuki.jp/entry/2018/12/05/160649 -
.NET Core3.0でWindows Forms/WPFが
サポートされたので早速試してみた - あるSEのつぶやき・改
https://www.aruse.net/entry/2018/12/05/100935 -
Visual Studio 2019で始める「WPF on .NET Core 3.0」開発
というタイトルで登壇してきました - nuits.jp blog
http://www.nuits.jp/entry/wpf-on-dot-net-core-3_0
-
既存の WPF アプリケーションを .NET Core 3.0 に移行した
https://blog.shibayan.jp/entry/20190302/1551518606 -
.NET Core 3.0 Preview 7 で Go Live が付いたので
WPF アプリケーションを更に対応させた
https://blog.shibayan.jp/entry/20190725/1564045069 -
.NET Core 3.0 で WinForms / WPFを
使う場合は実行ファイルのパスに注意
https://blog.shibayan.jp/entry/20190909/1568007641
- .NET Core 3.0 でデスクトップアプリを作る (目次)
https://rksoftware.hatenablog.com/entry/2019/01/10/203234-
.NET Core 3.0 でデスクトップアプリを作る(VS プレビュー版を使わない)
-
.NET Core 3.0 プロジェクトの発行でエラーになる
-
.NET Core 3.0 デスクトップアプリプロジェクトが
- Visual Studio 2019 で開けない
- ビルドできない
-
デザイナがなくても問題なし
- .NET Core 3.0 で Windows フォームアプリケーションを作る
- Windows フォーム手書き時の注意 AutoScaleDimensions 設定
-
帳票出力
- .NET Core デスクトップアプリケーションから DioDocs を使って帳票を PDF 出力する
- .NET Core デスクトップアプリケーションで PDF 帳票を画面表示する
- .NET Core デスクトップアプリケーションで DioDocs で作った PDF 帳票を印刷する
-
- Windows Forms アプリを .NET Core 3.0 に移植する
https://learn.microsoft.com/ja-jp/dotnet/core/porting/winforms - WPF アプリを .NET Core 3.0 に移植する
https://learn.microsoft.com/ja-jp/dotnet/core/porting/wpf
-
Windows 互換機能パックを使用してコードを .NET Core に移植する - .NET Core
https://learn.microsoft.com/ja-jp/dotnet/core/porting/windows-compat-pack- designs/compat-pack.md at master · dotnet/designs
https://github.com/dotnet/designs/blob/main/accepted/2018/compat-pack/compat-pack.md
- designs/compat-pack.md at master · dotnet/designs
移行メモ(リンクの誤り): 移行元では
「designs/compat-pack.md at master · dotnet/designs」の URL が、
直前の項目(Microsoft Docs の互換機能パック)と同一になっていた。
リンク テキストが指す GitHub 上の設計文書(dotnet/designs)の URL に置き換えた。
Tags: 移行, .NET開発, .NET Core
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。