file-based apps を Visual Studio Code でデバッグする
概要
.NET10 で利用可能となった file-based apps は、従来プロジェクトファイルで指示していたビルド設定をC#ソースファイル内に記述して、単一ファイルでビルドや直接実行(のようにみえるインスタントビルド)を行える機能です。
おおよそスクリプトのような感覚で利用できるため多方面に便利な道具となります。
この file-based apps をデバッグするための方法を調べてわかった点を記事にしています。
普通に実行する方法や環境準備などは省略します。
file-based apps として扱わせるために
ソースファイルを file-based apps として dotnet に扱ってもらうためには、実行可能コードを含んでいるうえで、以下のいずれかである必要があります。
- ファイル拡張子が .cs である。
- ファイル先頭に shebang がある。(拡張子は問わない)
-
dotnet runコマンドに--fileオプションを付与する。(拡張子は問わない)
dotnet コマンドにファイルを渡した際、Windows上でも shebang の検出をして file-based apps であるかの判定を行っているらしく、これによってファイルの拡張子はなんでも良くなります。(ただし、BOMが付いているとshebangを認識できないようです。[1])
個人的にはこれがとても便利[2]であるため、Windowsでしか利用しないとしても常に shebang を付与しておくのがよさそうだと思っています。
デバッグの利用環境
基本環境として Visual Studio Code と拡張機能 C# が必要になります。
そのうえで、拡張機能 C# Dev Kit を使う方法と使わない方法を紹介していきます。
C# Dev Kit はライセンスを要する拡張機能であり、利用可能でない場合もあるかと思います。
共通の設定項目
ファイル拡張子を .cs 以外にする場合、vscode設定項目 [Files: Associations] (設定ID:files.associations) にて、利用する拡張子を csharp に紐づけておくことで .cs と同じように扱われます。(そして先述の shebang によって file-based apps 扱いにさせることができます)
また、デバッグとは直接関係ありませんが、設定項目 [Dotnet › Projects: Enable File Based Programs] (設定ID:dotnet.projects.enableFileBasedPrograms) を有効にしておくと編集支援が効いて便利です。
ワークスペースの設定ファイルにこれらを保存しておくと便利かと思います。(参考)
C# Dev Kit を利用する場合
C# Dev Kit はなんの設定もなく[3]自動判別で file-based apps のデバッグを行える機能を持っているため、単純にワークスペース内の file-based apps ファイルを開いて [デバッグの開始] を行うだけで済みます。
初回は [C#]-[C#: Debug Active File-Based App] を選択する必要があるかもしれません。
自分で tasks.json/launch.json を用意する場合
file-based apps の実行起点はソースファイルであっても、実行プロセス自体はビルドされた実行ファイルから起動されたものであるので、通常のC#プログラムの場合と同様にデバッグアタッチする実行ファイルを指定できれば良いということになります。
そのため、以下を用意することでデバッグ可能になります。[4]
- 適当な場所に file-based apps をビルド出力する
tasks.json - 出力されたDLLを起動する
launch.json
以下に、その設定ファイル内容の例を示します。
ここでは、Windowsで定義されている環境変数 TEMP のディレクトリ配下にビルド出力を行い、それを起動する例になっています。
出力場所は環境に合わせて適切に選択する必要があるかと思います。
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${file}",
"--output",
"${env:TEMP}/cs-filebased/${fileWorkspaceFolderBasename}/${relativeFileDirname}/${fileBasenameNoExtension}"
],
"problemMatcher": "$msCompile"
}
]
}
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${env:TEMP}/cs-filebased/${fileWorkspaceFolderBasename}/${relativeFileDirname}/${fileBasenameNoExtension}/${fileBasenameNoExtension}.dll",
"args": [],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"stopAtEntry": false
}
]
}
Discussion