LoginSignup
2
1

More than 3 years have passed since last update.

Visual Studio 2017でビルドしているWinFormsアプリを.NET Coreでも並行開発可能にする方法

Last updated at Posted at 2020-06-27

日記に近いメモです。

前置き

メンテナンスしている、とあるWinFormsアプリは.NET Frameworkで動作しているのですが、開発者としては.NET 5に備え.NET Core 3.1に移行したいところです。
しかし、手元のWinFormsアプリはVisual Studio 2017 Expressで開発しているので、そう簡単に.NET Core(の新しいcsproj形式)に移行できません。
WinFormsデザイナーが使用できないと、UIに手を入れるのが非常に面倒になります。

そこで「移行」するのではなく、Visual Studio 2017(.NET Framework)で開発可能なまま.NET Coreでもビルドできる状態を目指していきます。
(使用していないソースコードを削除する以外は、ソースコードは変えません。)
Visual Studio 2019が使えればこんな面倒なことはしません。

対象のソースコード

下記のようなディレクトリ構成だとします。細かいファイルは省略してます。
なお、このアプリはx86でしか動作しませんが、開発環境はx64です。

SolutionFolder/
├───MyApps.sln
├───MyFormsApp/
│   ├───MyForms.csproj
│   ├───Form1.cs
│   ├───...
│   └───Program.cs
└───MyLib/
    └───MyLib.csproj

準備

基本的にはWindows フォーム デスクトップ アプリを .NET Core に移植する方法を参考にします。

.NET Portability Analyzer

.NET Portability Analyzer で事前に検証すべきですが、最近はWindows 互換機能パックにより互換性が高めなので、明らかに.NET Coreで使用できない機能(WCFとか)を使用していないのであれば、自己責任でやらなくてもいいかもしれません。

.NET Core SDK

アプリはx86でしか動作しませんが、開発環境に合わせて.NET Core 3.1 SDK x64をインストールします。

dotnetコマンドが動作すること確認しておきます。

PS > dotnet --list-sdks
3.1.100 [C:\Program Files\dotnet\sdk]
PS > dotnet --list-runtimes
Microsoft.AspNetCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]

csprojに含まれないソースコードを削除する

.NET Coreではワイルドカードでソースコードを指定するため、使用していないソースコード(ゴミ)が残っている場合は削除しておきます。

新しいcsprojを作成する

docs.microsoft.comの例に倣い、MyFormsAppCoreというディレクトリを作成して、その中に.NET Core用のプロジェクトを作ります。

MyFormsAppの中に作ると、dotnetコマンドで毎回プロジェクトファイルを指定しないと行けないので面倒になります。

SolutionFolder/
├───MyApps.sln
├───MyFormsApp/
│   ├───MyForms.csproj
│   ├───Form1.cs
│   ├───...
│   └───Program.cs
├───MyLib/
│   └───MyLib.csproj
└───MyFormsAppCore/      <--- New folder for core project

dotnet/try-convertというツールもありますが、今回は手動で行います。

PS > cd SolutionFolder/MyFormsAppCore
PS SolutionFolder\MyFormsAppCore> New-Item -Type File MyFormsAppCore.csproj

dotnet new winformsコマンドで作成してもいいんですが、
どうせ*.csファイルを消して.csprojファイルを作成する必要があるので直接作ります。

csprojの編集

下記を貼り付けます。

MyFormsAppCore.csproj
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UseWindowsForms>true</UseWindowsForms>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <AssemblyName>MyCoreApp</AssemblyName>
    <RootNamespace>WindowsFormsApp1</RootNamespace>
    <Deterministic>false</Deterministic>
    <LangVersion>7.3</LangVersion>
    <PlatformTarget>x86</PlatformTarget>
    <RuntimeIdentifier>win-x86</RuntimeIdentifier>
  </PropertyGroup>

  <ItemGroup>
    <Compile Include="..\MyFormsApp\**\*.cs" Exclude="..\MyFormsApp\obj\**\*.cs" />
    <EmbeddedResource Include="..\MyFormsApp\**\*.resx" />
  </ItemGroup>

</Project>
  • AssemblyName / RootNamespace は実際のプロジェクトに合わせて(古いcsprojファイルを参照して)変えます。
  • LangVersionは Visual Studio 2017で使用可能な7.3までにします。
  • AssemblyVersion.csで、[assembly: AssemblyVersion("1.0.*")]のようなワイルドカードを使用していたので、エラー CS8357が発生します。今回はソースコードは変えない前提なので、<Deterministic>false</Deterministic>を追加します。
  • Visual Studio 2017でビルドしていると、objディレクトリ内に自動生成された*.csファイルが作成されるので、Exclude属性で除外しています。
  • 前述の通り、x86でしか動作しないのでPlatformTargetx86を指定しています。
  • x86でしか動作しないWinFormsアプリなので、コマンドラインでの指定を省略できるようにRuntimeIdentifierwin-x86を指定しています。x64でも動作させるなら、指定は外しておくべきでしょう。

追加の編集

デフォルトで、ある程度使える設定はされていますが、何も設定をしなくていいわけではありません。
下記の設定(タグ)を、旧csprojからコピペが必要でした。
パスも調整する必要があります。

  • ApplicationIcon
  • ApplicationManifest

NuGet参照

使用するライブラリの精査が面倒なら、 Windows 互換機能パックへの参照を追加します。

PS SolutionFolder\MyFormsAppCore> dotnet add package Microsoft.Windows.Compatibility

手元のプロジェクトだとMEFを使用していたので、

PS SolutionFolder\MyFormsAppCore> dotnet add package System.Composition

だけで済みました。

プロジェクト参照

使用するライブラリへの参照を追加します。
元のMyFormsApp.csprojの中から、..\MyLib\MyLib.csprojを指定しているItemGroupタグをコピーして、MyFormsAppCore.csprojに貼り付けます。

...
  <ItemGroup>
    <ProjectReference Include="..\MyLib\MyLib.csproj">
    <Project>{8E29561D-E424-4AAB-A4FA-E966EF653A0F}</Project>
    <Name>MyLib</Name>
  </ItemGroup>
...

ライブラリ自体は.NET Frameworkのままですが、結果的に手元のプロジェクトは何もせずにビルドできました。
正しくは事前に.NET Coreプロジェクト化したcsprojを用意して、dotnet add referenceで追加する必要があるでしょう。

ビルド

上手く行っていれば、問題なくビルドできるはずです。

# Debugビルド
PS SolutionFolder\MyFormsAppCore> dotnet build
# Releaseビルド
PS SolutionFolder\MyFormsAppCore> dotnet build -c Reelase

実行

PS SolutionFolder\MyFormsAppCore> dotnet run

発行

発行する方法はいくつかありますが、batファイルを用意することにします。

dotnet publish -c Release --output publish

実行後、SolutionFolder\MyFormsAppCore\publish\MyCoreApp.exeが作成されているので、それを実行します。

PublishTrimmedPublishSingleFileを使用したければ、dotnet publishコマンドのリファレンスに従って、オプションは調整しましょう。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1