Skip to content

MS_DotNetCoreOnWSL

nishi_74322014 edited this page Sep 11, 2026 · 3 revisions

WSL上での.NET Core開発

概要

  • WSL を使用した、.NET Core, ASP.NET Core
    開発が可能。

  • 手軽に動作確認を行うなどの用途では、WSL は非常に便利だと思う。

  • ただし、所詮、エミュレーションなので、実機確認を行う場合は、
    Dockerなどを使用すべきと考える。

補足(本ページを今読む際の前提): 本ページは
WSL1 + .NET Core 2.0 + Ubuntu 16.04(xenial)という、
2018〜2019 年頃の構成を記録したものである。
現在は前提が大きく変わっている
ため、先に差分を示す。

【「所詮エミュレーション」という評価について】★
   ・【WSL1】はまさにそのとおりだった
     → Linux のシステムコールを
       Windows カーネルが【翻訳して実行】する
     → 本物の Linux カーネルではない
     → 一部のシステムコールが未実装
     → ファイル I/O が極端に遅い ★

   ・【WSL2】(2020年〜)で前提が変わった
     → 【本物の Linux カーネル】が
       軽量 Hyper-V VM 上で動く ★
     → 互換性の問題がほぼ解消
     → Docker Desktop も WSL2 backend を採用
     → 「エミュレーション」ではなくなった
     → 詳細は [WSL → WSL2](MS_WSLToWSL2)

【現在の開発スタイル】★
   ・【VS Code + WSL 拡張(Remote - WSL)】★★
     → 本ページのような
       「SSH + PuTTY + launch.json 手書き」は【不要】
     → VS Code が WSL 内でサーバ部分を動かし、
       UI だけ Windows 側に出す
     → F5 でそのままデバッグできる
   ・【Dev Container】
     → 環境定義ごとコード化する
   ・Visual Studio(本体)でも
     【WSL2 起動プロファイル】が標準搭載された
       launchSettings.json に "WSL" プロファイルが出る ★

準備

WSL

インストール

Windows Subsystem for Linux を参照。

設定

  • hostname : nishino
  • username : seigi
  • username@hostname : seigi@nishino
Installing, this may take a few minutes...
Installation successful!
Please create a default UNIX user account. The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username: seigi
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Default UNIX user set to: seigi
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

dotnet

2.n

sudo apt-get update
sudo apt-get install openssh-server unzip curl
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial main" > /etc/apt/sources.list.d/dotnetdev.list'
sudo apt-get update
sudo apt-get install dotnet-sdk-2.n
dotnet --version

3.n

...

移行メモ(未執筆): 「3.n」の節は移行元でも「...」のみで
本文が存在しない。見出しは残した。

補足(現在のインストール手順): 上記の手順は
Ubuntu 16.04(xenial)向けであり、現在は使えない。

【現在(Ubuntu 22.04 / 24.04)】★
   # Microsoft のパッケージ リポジトリを登録
   wget https://packages.microsoft.com/config/ubuntu/24.04/packages-microsoft-prod.deb \
        -O packages-microsoft-prod.deb
   sudo dpkg -i packages-microsoft-prod.deb
   rm packages-microsoft-prod.deb
   sudo apt-get update
   sudo apt-get install -y dotnet-sdk-8.0

【さらに簡単な方法】★
   ・Ubuntu 22.04 以降は
     【標準リポジトリにも .NET が入っている】
       sudo apt install dotnet-sdk-8.0
     → ただし Microsoft 版と混在させると
       競合することがあるので【どちらか一方に統一する】★

   ・【dotnet-install スクリプト】(root 不要)
       curl -sSL https://dot.net/v1/dotnet-install.sh | bash -s -- --channel 8.0
     → ~/.dotnet に入る。複数版の共存が容易

【apt-key の廃止】★
   ・原文の
     「/etc/apt/trusted.gpg.d/ に .gpg を置く」方式は
     現在も動くが、
     Ubuntu 22.04 以降は
     【signed-by で個別に指定する】のが推奨
       deb [signed-by=/usr/share/keyrings/microsoft.gpg] ...
     → packages-microsoft-prod.deb を使えば
       自動的に適切に設定される ★

dotnet new

dotnet new コマンドを使用した、テンプレート準備とビルド・実行。

seigi@nishino:~$ curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   983  100   983    0     0    319      0  0:00:03  0:00:03 --:--:--   319
seigi@nishino:~$ sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
[sudo] password for seigi:
seigi@nishino:~$ sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial main" > /etc/apt/sources.list.d/dotnetdev.list'
seigi@nishino:~$ sudo apt-get update
Get:1 http://security.ubuntu.com/ubuntu xenial-security InRelease [107 kB]
Hit:2 http://archive.ubuntu.com/ubuntu xenial InRelease
Get:3 https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial InRelease [2,845 B]
...
Fetched 15.7 MB in 16s (944 kB/s)
Reading package lists... Done
seigi@nishino:~$ sudo apt-get install dotnet-sdk-2.0.0
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  aspnetcore-store-2.0.0 dotnet-host dotnet-hostfxr-2.0.0 dotnet-runtime-2.0.0 dotnet-runtime-deps-2.1.0-rc1
  dotnet-sdk-2.0.0 libcurl3 liblttng-ust-ctl2 liblttng-ust0 libunwind8 liburcu4
0 upgraded, 11 newly installed, 0 to remove and 135 not upgraded.
Need to get 108 MB of archives.
After this operation, 309 MB of additional disk space will be used.
Do you want to continue? [Y/n] Y
...
Setting up dotnet-sdk-2.0.0 (2.0.0-1) ...
This software may collect information about you and your use of the software, and send that to Microsoft.
Please visit http://aka.ms/dotnet-cli-eula for more information.
Welcome to .NET Core!
---------------------
Learn more about .NET Core @ https://aka.ms/dotnet-docs. Use dotnet --help to see available commands or go to https://aka.ms/dotnet-cli-docs.

.NET Core Tools Telemetry
--------------
The .NET Core Tools include a telemetry feature that collects usage information. It is important that the .NET Team understands how the tools are being used so that we can improve them.

移行メモ(体裁): 上記のコンソール ログは移行元で
apt-get update / apt-get install取得・展開ログが
100 行以上そのまま貼られていた
ため、
手順の理解に必要な冒頭・要点・末尾を残して中略した
(中略箇所は ... で示している)。
全文は移行元(PukiWiki ダンプ)に残っている。

補足(テレメトリの無効化): 上記ログの最後に出ている
テレメトリは、環境変数で止められる

【無効化】★
   export DOTNET_CLI_TELEMETRY_OPTOUT=1
   → ~/.bashrc や Dockerfile に入れておく

【他によく使う環境変数】
   DOTNET_NOLOGO=1
     → 初回実行時の「Welcome to .NET」表示を抑止
   DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
     → 初回のパッケージ展開を抑止(3.x 以前)
   → CI やコンテナ ビルドでは
     【この 2 つを入れるのが定石】★

dotnet publish

Visual Studio で作成したものを「/mnt/c」(後述の「※ 1」)を経由で、

  • ビルド(dotnet publish)
  • 実行(後述の「dotnet *.dll」)
cd /mnt/c/ConsoleApp1/ConsoleApp1
dotnet publish -c Release -r ubuntu.16.04-x64 --self-contained
cd bin/Release/netcoreapp2.0/ubuntu.16.04-x64
dotnet ConsoleApp1.dll
Hello World!

※ SCD(.NET Coreのデプロイ を参照)

dotnet *.dll

Visual Studio で作成・ビルドしたものを「/mnt/c」(後述の「※ 1」)を
経由して実行

dotnet /mnt/c/ConsoleApp1/ConsoleApp1/bin/Debug/netcoreapp2.0/ConsoleApp1.dll
Hello World!

※ FDD(.NET Coreのデプロイ を参照)

補足(/mnt/c 経由のビルドは避けるべき): 本ページの手順の中核だが、
WSL2 では性能上の大きな落とし穴になる

【ファイル I/O の性能】★★
   WSL1
     → /mnt/c へのアクセスは【比較的速い】
       (Windows のファイル システムを直接叩く)
   WSL2
     → /mnt/c へのアクセスは
       【9P プロトコル経由】になり【極端に遅い】★
     → npm install / dotnet restore /
       dotnet build が【数倍〜十数倍遅くなる】

【現在の鉄則】★★
   ・【Linux 側のファイル システム(~/)で作業する】
     → ~/src/myapp に clone してビルドする
   ・Windows 側から参照したい場合は
     【\\wsl$\Ubuntu\home\...】(エクスプローラで開ける)
   ・逆方向(Windows のファイルを WSL で扱う)は
     【避ける】

【VS Code の Remote - WSL がやっていること】★
   ・ソースは WSL 側に置いたまま
   ・VS Code サーバも WSL 側で動く
   ・UI だけ Windows 側
   → 【ファイルの跨ぎが発生しない】
   → だから速い
【-r ubuntu.16.04-x64 という RID について】★
   ・現在は【linux-x64】という
     汎用 RID を使うのが推奨 ★
       dotnet publish -c Release -r linux-x64 --self-contained
   ・.NET 5 以降、
     ディストリビューション固有の RID
     (ubuntu.16.04-x64 等)は
     【ポータブル RID に統合】された
   ・ARM なら linux-arm64
   ・Alpine(musl)は linux-musl-x64

dotnet new

dotnet new コマンドを使用した、準備と確認。

seigi@nishino:~$ dotnet new mvc
Creating this template will make changes to existing files:
  Overwrite   seigi.csproj
  Overwrite   Program.cs

Rerun the command and pass --force to accept and create.
seigi@nishino:~$
seigi@nishino:~$ dotnet new mvc --force
The template "ASP.NET Core Web App (Model-View-Controller)" was created successfully.
This template contains technologies from parties other than Microsoft, see https://aka.ms/template-3pn for details.

Processing post-creation actions...
Running 'dotnet restore' on /home/seigi/seigi.csproj...
  Restoring packages for /home/seigi/seigi.csproj...
  Restore completed in 3.83 sec for /home/seigi/seigi.csproj.

Restore succeeded.

seigi@nishino:~$ dotnet run
warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
      No XML encryptor configured. Key {89022286-2fdf-47e0-85d2-0047907c89b1} may be persisted to storage in unencrypted form.

Hosting environment: Production
Content root path: /home/seigi
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
^CApplication is shutting down...

seigi@nishino:~$

mvcの実行1

補足(ホーム ディレクトリ直下でプロジェクトを作らない): 上のログで
dotnet new mvc が既存ファイルの上書きを警告しているのは、
~ 直下で実行しているためである。

【何が起きているか】★
   ・dotnet new は
     【カレント ディレクトリ名】をプロジェクト名にする
     → ~ は /home/seigi なので
       【seigi.csproj】が作られる
   ・2 回実行すると上書き警告が出る

【正しい作法】★
   dotnet new mvc -o MyApp
   cd MyApp
   → 専用ディレクトリに作る
   → --force は【既存ファイルを壊しうる】ので
     安易に使わない
【"No XML encryptor configured" 警告について】★
   ・ASP.NET Core の【データ保護(Data Protection)】が
     鍵を【暗号化せずに保存する】という警告
   ・開発環境では無視してよい
   ・本番で問題になる場面
     → 複数インスタンスで鍵を共有していないと
       【インスタンスを跨ぐと
         Cookie / アンチフォージェリ トークンが無効になる】★
     → 対策
         - 鍵を共有ストレージ(Redis / Blob / DB)に置く
         - X.509 証明書で保護する
         - PersistKeysToXxx + ProtectKeysWithXxx
     → 詳細は
       [ASP.NET Coreのデータ保護](MS_ASPNETCoreDataProtection)

dotnet publish

前述の「.NET Coreの開発」の dotnet publish と同上。

dotnet run

Visual Studio で作成・ビルドしたものを「/mnt/c」(後述の「※ 1」)を
経由して実行

seigi@nishino:~$ cd /mnt/c/WebApplication1/WebApplication1/
seigi@nishino:/mnt/c/WebApplication1/WebApplication1$ dotnet run
Using launch settings from /mnt/c/WebApplication1/WebApplication1/Properties/launchSettings.json...
info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0]
      User profile is available. Using '/home/seigi/.aspnet/DataProtection-Keys' as key repository; keys will not be encrypted at rest.
Hosting environment: Development
Content root path: /mnt/c/WebApplication1/WebApplication1
Now listening on: http://localhost:53336
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:53336/
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Executing action method WebApplication1.Controllers.HomeController.Index (WebApplication1) with arguments ((null)) - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewResultExecutor[1]
      Executing ViewResult, running view at path /Views/Home/Index.cshtml.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action WebApplication1.Controllers.HomeController.Index (WebApplication1) in 6636.097ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 7032.349ms 200 text/html; charset=utf-8
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2]
      Sending file. Request path: '/lib/jquery/dist/jquery.js'. Physical path: '/mnt/c/WebApplication1/WebApplication1/wwwroot/lib/jquery/dist/jquery.js'
...
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 1.081ms 200 image/x-icon

mvcの実行2

移行メモ(体裁): 上記のログも移行元では静的ファイル配信のログが
数十行にわたって記録されていたため、
要点(初回リクエストの処理時間、静的ファイル配信、最終行)を残して
中略した。

補足(初回リクエストが 6.6 秒かかっている理由): このログの数値は
WSL1 + /mnt/c の性能特性を端的に示している

【6636 ms の内訳(推定)】★
   ・【Razor ビューの初回コンパイル】
     → .NET Core 2.x では実行時コンパイルが既定
     → 2 回目以降は速い
   ・【/mnt/c 越しのファイル読み込み】★
     → ビュー、静的ファイル、アセンブリの読み込みが
       すべて Windows のファイル システム越し

【改善策】
 ① 【WSL 側(~/)にソースを置く】★
 ② 【Razor のビルド時コンパイル】
     → .NET Core 3.0 以降は【既定でビルド時】に変わった
     → 実行時コンパイルが必要なら
       Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation
 ③ 【ReadyToRun】発行で JIT を減らす
     → [ReadyToRun + Tiered Compilation](MS_ReadyToRunAndTieredCompilation)

OSバージョンの確認

以下のような感じ。

OperatingSystem os = Environment.OSVersion;
if (os.Platform == PlatformID.Win32NT)
{
    ・・・

補足(Environment.OSVersion による判定は現在は不適切): この方法は
.NET Core 以降、意図した動作をしない

【問題】★
   ・.NET Core / .NET 5+ では
     【Linux でも PlatformID.Unix】が返るが、
     macOS も同じく Unix を返していた時期がある
   ・そもそも PlatformID は
     【MacOSX / Xbox など古い値】を含み、混乱しやすい

【現在の正しい方法】★★
   using System.Runtime.InteropServices;

   if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) ...
   if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))   ...
   if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))     ...

   // .NET 5 以降はさらに簡潔
   if (OperatingSystem.IsWindows()) ...
   if (OperatingSystem.IsLinux())   ...
   if (OperatingSystem.IsWindowsVersionAtLeast(10, 0, 19041)) ...

【OperatingSystem.IsXxx() が優れている点】★
   ・【プラットフォーム互換性アナライザー(CA1416)】が
     この判定を理解する
     → Windows 専用 API を
       IsWindows() の中で呼べば警告が消える ★
     → RuntimeInformation では認識されないことがある

【WSL かどうかを判定したい場合】
   ・専用 API はない
   ・/proc/version に "microsoft" が含まれるかで判定するのが定番
     → ただし実装依存。恒久的な手段ではない

リモートデバッグ

C/C++

WSLのリモートデバッグ設定

以下は、すべて、WSL(Ubuntu)上の設定。

  • パッケージリストが古いと 404 になるので、以下を実行してから、
sudo apt-get update
  • コンパイラー、リモートデバッガ、SSH サーバのインストールを実施する。
sudo apt install -y build-essential
sudo apt install -y gdbserver
sudo apt install -y openssh-server
  • /etc/ssh/sshd_config ファイルを編集

    • 「vi」エディタで開く(viを参照)
sudo vi /etc/ssh/sshd_config
  • パスワード認証を有効にする。
# Change to no to disable tunnelled clear text passwords
PasswordAuthentication yes
  • SSH の鍵を作成する
sudo ssh-keygen -A
  • SSH サーバを起動する
sudo service ssh start
  • SSH サーバの状態を確認する。
sudo service ssh status

Visual Studio の設定

以下は、すべて、Windows 上の設定。

  • Visual Studio 2017 のインストーラーで、
    [C++ による Linux 開発]コンポーネントにチェック

  • [Visual C++]-[クロス プラットフォーム]-[Linux]を選択し、
    テンプレート一覧から「コンソール アプリケーション (Linux)」を選択。

  • F5 でデバッグ実行すると、WSL への接続ダイアログが表示され、接続が確立する。

    • [Host name:]欄には「localhost」
    • [User name:]欄と[Password]欄に(Ubuntu の)ユーザ / パスワード
    • [Connect]ボタンをクリックして WSL に接続。
  • 「gdb を起動できませんでした」と言うエラーが発生する場合、
    プロジェクトのプロパティの [デバッグ] → [デバッグ モード] を、
    gdb モードから、gdbserver モードへ、変更する。

補足(WSL1 で SSH を立てる際の注意): 本節の手順は
WSL1 特有の面倒を含んでいる。

【WSL1 での SSH サーバ】★
   ・【systemd がない】ため
     systemctl ではなく【service コマンド】を使う
     → 原文が service ssh start としているのは正しい ★
   ・WSL のシェルを閉じると
     【プロセスごと終了する】
     → 起動のたびに手で立ち上げ直す必要があった
   ・Windows 側の 22 番ポートと衝突しうる
     → sshd_config の Port を変える回避策が知られていた

【WSL2 での変化】★
   ・【systemd が使える】(2022年〜)
       /etc/wsl.conf に
         [boot]
         systemd=true
     → sudo systemctl enable --now ssh が使える
   ・ただし WSL2 は【独立した IP を持つ VM】
     → localhost 転送は Windows→WSL 方向のみ自動
     → 外部から WSL2 に入るには
       netsh のポート転送が要る

【そもそも SSH は不要になった】★★
   ・VS / VS Code は
     【WSL に直接アタッチする仕組み】を持つ
     → 本節の手順は
       「現在は必要ない」と理解してよい

.NET Core

仕組みとしては、

<Windows>
Visual Studio → DebugAdapterHost → PuTTY

↓ ↓ ↓(SSH)↑ ↑ ↑

<Linux>
openssh-server → vsdbg → dotnet (XXXX.dll)

みたいな感じで、

  • debugger を attach した
    remote process と

  • client IDE が

通信して debug する感じ。

WSLのリモートデバッグ設定

  • WSL(Ubuntu)上の設定。

    • 前述の C/C++ の手順と同様に、
      SSH サーバのインストールと設定を実施しておく。

    • unzip をインストールする(vsdbg のインストールで必要だったため)。

sudo apt-get install unzip
  • 次のコマンドを実行して vsdbg をインストールする。
    「-l」には、任意のインストール・パスを指定する。
curl -sSL https://aka.ms/getvsdbgsh | bash /dev/stdin -v vs2017u5 -l ~/vsdbg
  • トランスポートには、前述と同様に SSH を使用できる。

  • Windows 上の設定。

    • PuTTYをインストールして、
    • PuTTYで SSH サーバを接続する。

Visual Studio の設定

  • デバッグ対象のプロジェクトはポータブル PDB を指定。

  • Windows 上でビルドが通ったら、

    • そのまま次のステップに進む(FDD)
    • Linux 上で前述の dotnet publish する(SCD)
      ファイルの共有については、「/mnt/c」(後述の「※ 1」)を経由で、

    ※ FDD がイイのか?SCD がイイのか?
    .NET Coreのデプロイ を参照)

  • 起動構成ファイル(launch.json)を作成する。

    • Visual Studio にデバッグ方法を指示する
    • プロジェクトを起動する launch.json ファイルの例を次に示す。
{
  "version": "1.0.0",
  "adapter": "C:\\Program Files\\PuTTY\\plink.exe",
  "adapterArgs": "-i c:\\private.ppk seigi@nishino -batch -T ~/vsdbg/vsdbg --interpreter=vscode",
  "configurations": [
    {
      "name": ".NET Core Launch",
      "type": "coreclr",
      "cwd": "/mnt/c/xxxx",
      "program": "bin/Debug/netcoreappn.n/.../xxxx.dll",
      "request": "launch"
    }
  ]
}

※ コレは、SCD のパターンか。

  • adapter
    トランスポートとして SSH を使用

    • SSH クライアントは PuTTY(plink.exe)を使用する。
    • SSH サーバーを経由して vsdbg に接続する。
  • adapterArgs
    PuTTY(plink.exe)のコマンドライン引数

    • プライベート SSH キーへのパス
    • SSH Linux ボックスに接続するように指示
    • vsdbg インストール・ディレクトリから、
      vsdbg 実行可能ファイルを実行
  • configurations
    vsdbg に渡す設定値

    • cwd
      ・Linux 上の、プロジェクトのルート・ディレクトリ
      ・若しくは、実行可能ファイルの配置先ディレクトリ

    • program
      ・Linux 上の、実行可能ファイルへのパス
      ・若しくは、実行可能ファイル名
      ・(vsdbg は dotnet コマンドで実行可能ファイルを実行)

移行メモ(誤字): 移行元の「ファイル共有については」を
「ファイル共有については」に修正した。

デバッグ実行を開始

  • 冒頭に書いた通り、DebugAdapterHost 経由で、デバッグ実行を開始。
    • [表示] メニュー > [その他のウィンドウ] > [コマンド ウィンドウ]
    • 以下のコマンドを、Visual Studio のコマンドウィンドウに打ち込む。
DebugAdapterHost.Launch /LaunchJson:"launch.jsonファイルのフルパス"

※ ファイル名は「launch.json」でなくてもイイもよう。

補足(vsdbgDebugAdapterHost の位置付け): 本節の仕組みは
今も内部的には使われているので、理解しておく価値がある。

【vsdbg(Visual Studio Debugger for Linux)】★
   ・Linux / macOS 上で動く .NET のデバッガ本体
   ・【VS Code の C# 拡張も同じものを使う】★
     → つまり VS / VS Code / Rider(独自)で
       デバッグ体験が共通化されている
   ・ライセンスは
     【Microsoft のツールからの利用に限定】される点に注意

【DAP(Debug Adapter Protocol)】★★
   ・原文の --interpreter=vscode が示すとおり、
     vsdbg は【VS Code のデバッグ プロトコル】を話す
   ・DAP は Microsoft が策定した
     【IDE とデバッガの間の共通プロトコル】
     → LSP(Language Server Protocol)のデバッグ版
     → 1 つのデバッガを多数の IDE が使える ★
   ・DebugAdapterHost は
     Visual Studio 側の DAP クライアント

【現在の簡単な方法】★
   ・VS Code
     → Remote - WSL で開けば
       【launch.json も自動生成】され、F5 で動く
   ・Visual Studio
     → launchSettings.json に
       【WSL プロファイル】が標準で用意される
     → 本節のような手書き launch.json は不要 ★

ASP.NET Core

WSLのリモートデバッグ設定

  • WSL(Ubuntu)上の設定。

    • 以下を除き、前述の .NET Core と同じ。
    • dotnet 2.1 以上。
  • Windows 上の設定。

    • 以下を除き、前述の .NET Core と同じ。
    • dotnet 2.1 以上。

Visual Studio の設定

以下を除き、前述の .NET Core と同じ。

  • 以下を Program.Main メソッドに追加する。
    (リモートデバッグではブラウザが自動起動しないのでポートを明示)
CreateWebHostBuilder(args).UseUrls("http://*:5000").Build().Run();

デバッグ実行を開始

以下を除き、前述の .NET Core と同じ。

補足(UseUrls("http://*:5000") の意味と、現在の書き方): この指定は
WSL2 では意味が変わるので補っておく。

【なぜ * が必要か】★
   ・既定の localhost バインドは
     【そのマシンの中からしか繋がらない】
   ・WSL1 は Windows とネットワークを共有していたため
     localhost でも繋がったが、
     明示した方が確実だった
   ・WSL2 は【別 IP の VM】
     → 0.0.0.0(=*)にバインドしないと
       Windows 側から繋がらない ★
     → ただし WSL2 には
       【localhost 転送】機能があり、
       多くの場合 localhost:5000 で繋がる

【現在の書き方(.NET 6 以降の最小 API)】★
   ・コード
       app.Run("http://0.0.0.0:5000");
   ・環境変数(推奨)★
       ASPNETCORE_URLS=http://0.0.0.0:5000
   ・launchSettings.json の applicationUrl
   → 【コードに埋め込まないのが定石】
     (環境ごとに変わるため)

【セキュリティ上の注意】
   ・0.0.0.0 バインドは
     【同一ネットワークの他マシンからも見える】★
   ・開発機では
     ファイアウォールで塞がれていることが多いが、
     意識しておくこと

Visual Studio からデバッガをアタッチする方法

WSLのリモートデバッグ設定

  • 以下を除き、前述の .NET Core、ASP.NET Core と同じ。

  • 事前に、アプリケーションを起動しておく(自動で Launch しないので)。

dotnet /.../xxxx.dll
  • ConsoleApp では、アプリケーションが瞬時に終了してしまうため、
    必要に応じて、Console.ReadKey などで止める必要はある。

Visual Studio の設定

  • 以下を除き、前述の ASP.NET Core と同じ。

    • launch.json を自作する必要はない。
    • SSH クライアントの PuTTYも不要(OS 組込のモノを使用する)
  • Visual Studio のメニューから
    [ツール] → [オプション] → [オプション] ダイアログ
    → [クロスプラットフォーム] → [接続マネージャー] → [追加]
    → [リモートシステムへの接続] ダイアログにて下記の情報を入力。

    • ホスト名 : localhost (任意)
    • ポート : 22
    • ユーザー名 : seigi
    • 認証の種類 : パスワード or 秘密鍵

デバッグ実行を開始

  • 事前に、アプリケーションを起動しておく。

  • Visual Studio のメニューから
    [デバッグ] → [プロセスにアタッチ] → [プロセスにアタッチ] ダイアログ

    • 接続の種類 : SSH
    • 接続先 : seigi@localhost (検索して選択)
    • アタッチ先 : [Managed(.NET Core for Unix) コード]
  • [使用可能なプロセス] から選択し、[アタッチ] ボタンを押下

    • プロセスが dotnet
    • タイトルが dotnet /.../xxxx.dll
  • デバッグ対象ファイルを開いて、ブレークポイントを指定する。

  • 起動したアプリケーションを実行する。

  • 以下の様に、リモートデバッグが実行される。
    https://twitter.com/openhishopjpo/status/1167284051515887618

移行メモ(誤字): 移行元の「[Maneged(.NET Core for Unix) コード]」を
「[Managed(.NET Core for Unix) コード]」に修正した。

補足(「アタッチ」方式が本ページで最も実用的): 3 通り紹介されている中で、
この方式が最も汎用性が高い

【この方式の利点】★
   ・launch.json を書かなくてよい
   ・PuTTY が要らない(Windows 標準の OpenSSH を使う)
   ・【すでに動いているプロセス】に後から入れる
     → 本番に近い状態(サービスとして起動中、
       コンテナ内)でも調査できる ★

【必要な条件】
 ① 【シンボル(PDB)が一致していること】★
     → portable PDB を発行に含める
       <DebugType>portable</DebugType>
     → 最適化ビルドだとステップ実行が飛ぶ
 ② vsdbg がリモート側にあること
     → VS が初回に自動転送することもある
 ③ 【権限】
     → 別ユーザーのプロセスには入れない

【コンテナへのアタッチ】★
   ・Visual Studio / VS Code は
     【実行中のコンテナへのアタッチ】にも対応する
     → 接続の種類で Docker を選ぶ
   ・本ページの SSH 方式の発展形と考えてよい

WSL2では何がどう変わったのか?

WSL → WSL2 の該当節を参照。

参考

※ 1

DrvFs の VFS ファイルシステムプラグイン。
WSLでのWindowsとLinuxの相互運用を参照)

トレースによるデバッグ

dotnetコマンド の該当節を参照。

リモートデバッグが難しい場合はコチラ。

リモートデバッグ

C/C++

.NET Core

OSSコンソーシアム

開発基盤部会 Blog

移行メモ(リンク切れ): Build Insider は 2019 年に更新を終了しており、
今後の到達性は保証されない。
また twitter.com のリンクは X への改称に伴い x.com へ移行しており、
個別の投稿が残っているかは保証されない。記録として残す。


Tags: 移行, .NET開発, .NET Core, Windows, Linux, Linuxサブシステム, 仮想化

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally