dotnet.exeでconsole,wpf,classlibを1つのソリューションで構築しvscodeでデバック実行する方法

C# コンピュータ
C#

コードを再利用することを考えるとクラスライブラリ(classlib)として作成するのが望ましい。
dotnet.exeのでclasslibのプロジェクトは以下のコマンドで作成することが出来ます。

クラスライブラリプロジェクトの作成コマンド

dotnet.exe new classlib -n <プロジェクト名>

プロジェクトを作ることは出来ますし、vscodeで普通にコーディングすることが出来るのですが、クラスライブラリにはエントリーポイントが存在しないので、デバック実行することが出来ません。クラスライブラリはエントリポイントを持つプロジェクトから参照されることによって実行されるプロジェクトです。

クラスライブラリプロジェクトを参照するコマンド

dotnet add <参照するプロジェクトの.csproj> reference <クラスライブラリのプロジェクト.csproj>

これでクラスライブラリを参照することが出来ます。ただ、デバック実行で実行できるのはクラスライブラリを参照しているプロジェクトのコードのみで、クラスライブラリは対象外に成ります。

調べたところソリューションを使うとクラスライブラリをデバック実行の対象に含めるとことが出来るようです。

ソリューション名:
MayworkNet

プロジェクト名:
MayworkNet.ConsoleApp
MayworkNet.WPFApp
MayworkNet.Lib

# ソリューションフォルダの作成
mkdir MayworkNet
cd MayworkNet
# ソリューションファイルの作成
dotnet new sln
# クラスライブラリプロジェクトの作成
dotnet new classlib -n MayworkNet.Lib
# クラスライブラリプロジェクトをソリューションへ追加
dotnet sln add MayworkNet.Lib/MayworkNet.Lib.csproj
# コンソールプロジェクトの作成
dotnet new console -n MayworkNet.ConsoleApp
# コンソールプロジェクトをソリューションへ追加
dotnet sln add MayworkNet.ConsoleApp/MayworkNet.ConsoleApp.csproj
# WPFプロジェクトの作成
dotnet new wpf -n MayworkNet.WPFApp
# WPFプロジェクトをソリューションへ追加
dotnet sln add MayworkNet.WPFApp/MayworkNet.WPFApp.csproj
# WPFプロジェクトからクラスライブラリを参照
dotnet add MayworkNet.WPFApp/MayworkNet.WPFApp.csproj reference MayworkNet.Lib/MayworkNet.Lib.csproj
# コンソールプロジェクトからクラスライブラリを参照
dotnet add MayworkNet.ConsoleApp/MayworkNet.ConsoleApp.csproj reference MayworkNet.Lib/MayworkNet.Lib.csproj
# クラスライブラリをビルド
cd MayworkNet.Lib
dotnet build
cd ..

ソリューションファイルの置かれたディレクトリでvscodeを起動します。
デバック実行用のプロジェクトを作成するか問い合わせを「はい」で答えます。

次にコンソールとWPFのいずれのプロジェクトを対象にするかの問い合わせはコンソールを選びました。

デバック実行用に以下のファイルを書き換えます。

.vscode/launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            // IntelliSense を使用して、C# デバッグに存在する属性を確認します
            // 既存の属性の説明にホバーを使用する
            // 詳細については、https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md を参照してください
            "name": ".NET Core Launch (console)",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build-console",
            // ターゲット フレームワークを変更した場合は、プログラム パスを更新するようにしてください。
            "program": "${workspaceFolder}/MayworkNet.ConsoleApp/bin/Debug/net8.0/MayworkNet.ConsoleApp.dll",
            "args": [],
            "cwd": "${workspaceFolder}/MayworkNet.ConsoleApp",
            // 'console' フィールドの詳細については、https://aka.ms/VSCode-CS-LaunchJson-Console を参照してください
            "console": "internalConsole",
            "stopAtEntry": false,
            "symbolSearchPath": "${workspaceFolder}/MayworkNet.Lib/bin/Debug/net8.0/"
        },
        {
            "name": ".NET Core Launch (WPF)",
            "type": "coreclr",
            "request": "launch",
            "preLaunchTask": "build-wpf",
            "program": "${workspaceFolder}/MayworkNet.WPFApp/bin/Debug/net8.0-windows/MayworkNet.WPFApp.dll",
            "args": [],
            "cwd": "${workspaceFolder}/MayworkNet.WPFApp",
            "console": "internalConsole",
            "stopAtEntry": false,
            "symbolSearchPath": "${workspaceFolder}/MayworkNet.Lib/bin/Debug/net8.0/"
        },
        {
            "name": ".NET Core Attach",
            "type": "coreclr",
            "request": "attach"
        }
    ],
    "compounds": [
        {
            "name": "複合デバッグ",
            "configurations": [".NET Core Launch (WPF)", ".NET Core Launch (console)"]
        }
    ]    
}

.vscode/tasks.json

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build-console",
            "command": "dotnet",
            "type": "process",
            "args": [
                "build",
                "${workspaceFolder}/MayworkNet.ConsoleApp/MayworkNet.ConsoleApp.csproj",
                "/property:GenerateFullPaths=true",
                "/consoleloggerparameters:NoSummary;ForceNoAlign"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "build-wpf",
            "command": "dotnet",
            "type": "process",
            "args": [
                "build",
                "${workspaceFolder}/MayworkNet.WPFApp/MayworkNet.WPFApp.csproj",
                "/property:GenerateFullPaths=true",
                "/consoleloggerparameters:NoSummary;ForceNoAlign"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "publish",
            "command": "dotnet",
            "type": "process",
            "args": [
                "publish",
                "${workspaceFolder}/MayworkNet.ConsoleApp/MayworkNet.ConsoleApp.csproj",
                "/property:GenerateFullPaths=true",
                "/consoleloggerparameters:NoSummary;ForceNoAlign"
            ],
            "problemMatcher": "$msCompile"
        },
        {
            "label": "watch",
            "command": "dotnet",
            "type": "process",
            "args": [
                "watch",
                "run",
                "--project",
                "${workspaceFolder}/MayworkNet.ConsoleApp/MayworkNet.ConsoleApp.csproj"
            ],
            "problemMatcher": "$msCompile"
        }
    ]
}

基本的に既にあるconsoleをコピーしてWPFを追加するような形です。それに合わせて各種パス等のつじつま合わせを行っています。Debugフォルダを参照しているので、事前に各プロジェクトを”dotnet.exe build”でビルドしておくと良いでしょう。
また、クラスライブラリの参照は"symbolSearchPath": "${workspaceFolder}/MayworkNet.Lib/bin/Debug/net8.0/"を追記することでデバック実行時にクラスライブラリのコードにブレークポイントをセットすることが出来るようになります。

デバック実行で実行するプロジェクトを切り替える方法はデバック実行のアイコンをクリックし、コンボボックスで選択することが出来ます。

.NET Core Launch(console)か.NET Core Launch(WPF)のいずれかを選びます。

(複合デバックは用途不明)

デバック実行までの設定作業は以上となります。

以下動作確認のために書いたコードに成ります。

ファイル名:MayworkNet.ConsoleApp/Program.cs

// See https://aka.ms/new-console-template for more information
var str = MayworkNet.Lib.Class1.Hello();
Console.WriteLine($"{str}");

ファイル名:MayworkNet.Lib/Class1.cs

namespace MayworkNet.Lib;

public class Class1
{
    public static string Hello()
    {
        return "Hello, World!";
    }
}

ファイル名:MayworkNet.WPFApp/MainWindow.xaml.cs

using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MayworkNet.WPFApp;

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        var str = MayworkNet.Lib.Class1.Hello();
        System.Diagnostics.Debug.Print($"{str}");
    }
}

デバック実行を行いたい場合、基本的にソリューションファイルを置いたディレクトリでvscodeを開きます。

ディレクトリとファイル構造

MayworkNet
│  MayworkNet.sln
│  tree.txt
│  
├─.vscode
│      launch.json
│      tasks.json
│      
├─MayworkNet.ConsoleApp
│  │  MayworkNet.ConsoleApp.csproj
│  │  Program.cs
│  │  
│  ├─bin
│  │  └─Debug
│  │      └─net8.0
│  │              MayworkNet.ConsoleApp.deps.json
│  │              MayworkNet.ConsoleApp.dll
│  │              MayworkNet.ConsoleApp.exe
│  │              MayworkNet.ConsoleApp.pdb
│  │              MayworkNet.ConsoleApp.runtimeconfig.json
│  │              MayworkNet.Lib.dll
│  │              MayworkNet.Lib.pdb
│  │              
│  └─obj
│      │  MayworkNet.ConsoleApp.csproj.nuget.dgspec.json
│      │  MayworkNet.ConsoleApp.csproj.nuget.g.props
│      │  MayworkNet.ConsoleApp.csproj.nuget.g.targets
│      │  project.assets.json
│      │  project.nuget.cache
│      │  
│      └─Debug
│          └─net8.0
│              │  .NETCoreApp,Version=v8.0.AssemblyAttributes.cs
│              │  apphost.exe
│              │  MayworkN.AB7B9964.Up2Date
│              │  MayworkNet.ConsoleApp.AssemblyInfo.cs
│              │  MayworkNet.ConsoleApp.AssemblyInfoInputs.cache
│              │  MayworkNet.ConsoleApp.assets.cache
│              │  MayworkNet.ConsoleApp.csproj.AssemblyReference.cache
│              │  MayworkNet.ConsoleApp.csproj.CoreCompileInputs.cache
│              │  MayworkNet.ConsoleApp.csproj.FileListAbsolute.txt
│              │  MayworkNet.ConsoleApp.dll
│              │  MayworkNet.ConsoleApp.GeneratedMSBuildEditorConfig.editorconfig
│              │  MayworkNet.ConsoleApp.genruntimeconfig.cache
│              │  MayworkNet.ConsoleApp.GlobalUsings.g.cs
│              │  MayworkNet.ConsoleApp.pdb
│              │  
│              ├─ref
│              │      MayworkNet.ConsoleApp.dll
│              │      
│              └─refint
│                      MayworkNet.ConsoleApp.dll
│                      
├─MayworkNet.Lib
│  │  Class1.cs
│  │  MayworkNet.Lib.csproj
│  │  
│  ├─bin
│  │  └─Debug
│  │      └─net8.0
│  │              MayworkNet.Lib.deps.json
│  │              MayworkNet.Lib.dll
│  │              MayworkNet.Lib.pdb
│  │              
│  └─obj
│      │  MayworkNet.Lib.csproj.nuget.dgspec.json
│      │  MayworkNet.Lib.csproj.nuget.g.props
│      │  MayworkNet.Lib.csproj.nuget.g.targets
│      │  project.assets.json
│      │  project.nuget.cache
│      │  
│      └─Debug
│          └─net8.0
│              │  .NETCoreApp,Version=v8.0.AssemblyAttributes.cs
│              │  MayworkNet.Lib.AssemblyInfo.cs
│              │  MayworkNet.Lib.AssemblyInfoInputs.cache
│              │  MayworkNet.Lib.assets.cache
│              │  MayworkNet.Lib.csproj.CoreCompileInputs.cache
│              │  MayworkNet.Lib.csproj.FileListAbsolute.txt
│              │  MayworkNet.Lib.dll
│              │  MayworkNet.Lib.GeneratedMSBuildEditorConfig.editorconfig
│              │  MayworkNet.Lib.GlobalUsings.g.cs
│              │  MayworkNet.Lib.pdb
│              │  
│              ├─ref
│              │      MayworkNet.Lib.dll
│              │      
│              └─refint
│                      MayworkNet.Lib.dll
│                      
└─MayworkNet.WPFApp
    │  App.xaml
    │  App.xaml.cs
    │  AssemblyInfo.cs
    │  MainWindow.xaml
    │  MainWindow.xaml.cs
    │  MayworkNet.WPFApp.csproj
    │  
    ├─bin
    │  └─Debug
    │      └─net8.0-windows
    │              MayworkNet.Lib.dll
    │              MayworkNet.Lib.pdb
    │              MayworkNet.WPFApp.deps.json
    │              MayworkNet.WPFApp.dll
    │              MayworkNet.WPFApp.exe
    │              MayworkNet.WPFApp.pdb
    │              MayworkNet.WPFApp.runtimeconfig.json
    │              
    └─obj
        │  MayworkNet.WPFApp.csproj.nuget.dgspec.json
        │  MayworkNet.WPFApp.csproj.nuget.g.props
        │  MayworkNet.WPFApp.csproj.nuget.g.targets
        │  project.assets.json
        │  project.nuget.cache
        │  
        └─Debug
            └─net8.0-windows
                │  .NETCoreApp,Version=v8.0.AssemblyAttributes.cs
                │  App.g.cs
                │  App.g.i.cs
                │  apphost.exe
                │  MainWindow.baml
                │  MainWindow.g.cs
                │  MainWindow.g.i.cs
                │  MayworkN.754979FB.Up2Date
                │  MayworkNet.WPFApp.AssemblyInfo.cs
                │  MayworkNet.WPFApp.AssemblyInfoInputs.cache
                │  MayworkNet.WPFApp.assets.cache
                │  MayworkNet.WPFApp.csproj.AssemblyReference.cache
                │  MayworkNet.WPFApp.csproj.CoreCompileInputs.cache
                │  MayworkNet.WPFApp.csproj.FileListAbsolute.txt
                │  MayworkNet.WPFApp.dll
                │  MayworkNet.WPFApp.g.resources
                │  MayworkNet.WPFApp.GeneratedMSBuildEditorConfig.editorconfig
                │  MayworkNet.WPFApp.genruntimeconfig.cache
                │  MayworkNet.WPFApp.GlobalUsings.g.cs
                │  MayworkNet.WPFApp.pdb
                │  MayworkNet.WPFApp_2cpuyub0_wpftmp.AssemblyInfo.cs
                │  MayworkNet.WPFApp_2cpuyub0_wpftmp.AssemblyInfoInputs.cache
                │  MayworkNet.WPFApp_2cpuyub0_wpftmp.assets.cache
                │  MayworkNet.WPFApp_2cpuyub0_wpftmp.GeneratedMSBuildEditorConfig.editorconfig
                │  MayworkNet.WPFApp_2cpuyub0_wpftmp.GlobalUsings.g.cs
                │  MayworkNet.WPFApp_MarkupCompile.cache
                │  MayworkNet.WPFApp_MarkupCompile.lref
                │  MayworkNet.WPFApp_n5t223p5_wpftmp.AssemblyInfo.cs
                │  MayworkNet.WPFApp_n5t223p5_wpftmp.AssemblyInfoInputs.cache
                │  MayworkNet.WPFApp_n5t223p5_wpftmp.assets.cache
                │  MayworkNet.WPFApp_n5t223p5_wpftmp.GeneratedMSBuildEditorConfig.editorconfig
                │  MayworkNet.WPFApp_n5t223p5_wpftmp.GlobalUsings.g.cs
                │  MayworkNet.WPFApp_zv4vdawz_wpftmp.AssemblyInfo.cs
                │  MayworkNet.WPFApp_zv4vdawz_wpftmp.AssemblyInfoInputs.cache
                │  MayworkNet.WPFApp_zv4vdawz_wpftmp.assets.cache
                │  MayworkNet.WPFApp_zv4vdawz_wpftmp.GeneratedMSBuildEditorConfig.editorconfig
                │  MayworkNet.WPFApp_zv4vdawz_wpftmp.GlobalUsings.g.cs
                │  
                ├─ref
                │      MayworkNet.WPFApp.dll
                │      
                └─refint
                        MayworkNet.WPFApp.dll

環境構築まで少し面倒ですが、クラスライブラリで作成したコードをコンソールプロジェクトで試したり、WPFプロジェクトからクラスライブラリを利用出来たりと、実行環境を切り替えることが出来れば開発効率が向上すると思われます。

コメント