拡張ライブラリの開発・デバッグ
拡張ライブラリ を作るときの、ビルド → 配置 → デバッグの流れをまとめます。プリザンターは DLL を起動時にしか読まないため、「ビルドしたら ExtendedLibraries にコピーして、プリザンターを再起動し、デバッガを付ける」の繰り返しになります。コピーは MSBuild のターゲットで自動化できます。
前提
| 要件 | 内容 |
|---|---|
| .NET SDK | 本体と同じバージョン(1.5.8.1 は net10.0) |
| プリザンターのソース | 本体をプロジェクト参照する場合と、本体ごと起動してデバッグする場合に必要。プロセスにアタッチするだけなら公開済みバイナリでもよい |
| VS Code | C# Dev Kit または C# 拡張機能 |
| Visual Studio | 2022 以降 |
プロジェクト構成
MyExtendedLibrary/ ← 拡張ライブラリのリポジトリ
├── MyExtendedLibrary.sln
├── MyExtendedLibrary/
│ ├── MyExtendedLibrary.csproj
│ ├── ExtendedLibrary.cs ← 初期化クラス(任意)
│ ├── Controllers/
│ └── Api/
└── (../Implem.Pleasanter/) ← 本体のソース(隣に置くかサブモジュール)csproj
pdb を出力し、本体はプロジェクト参照だけにして出力にはコピーしません(Private="false"・ExcludeAssets="runtime")。本体と同じ名前の DLL を ExtendedLibraries に置くと本体側が優先され、バージョン違いでは実行時エラーの原因になるためです(読み込みで注意すること)。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>disable</Nullable>
<!-- デバッグシンボルを pdb ファイルとして出力 -->
<DebugType>portable</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<ProjectReference
Include="..\Implem.Pleasanter\Implem.Pleasanter.csproj"
Private="false"
ExcludeAssets="runtime" />
</ItemGroup>
</Project>ビルド後に ExtendedLibraries へコピーする
ビルドのたびに DLL と pdb をプリザンターの実行フォルダの ExtendedLibraries へコピーするターゲットを足します。PleasanterOutputDir は環境に合わせて変えてください(Implem.Pleasanter.dll があるフォルダです)。
<PropertyGroup>
<PleasanterOutputDir>..\Implem.Pleasanter\bin\Debug\net10.0</PleasanterOutputDir>
</PropertyGroup>
<Target Name="CopyToExtendedLibraries" AfterTargets="Build">
<ItemGroup>
<ExtendedLibraryFiles Include="$(OutputPath)$(AssemblyName).dll" />
<ExtendedLibraryFiles Include="$(OutputPath)$(AssemblyName).pdb" />
</ItemGroup>
<Copy
SourceFiles="@(ExtendedLibraryFiles)"
DestinationFolder="$(PleasanterOutputDir)\ExtendedLibraries"
SkipUnchangedFiles="true" />
<Message
Text="拡張ライブラリを $(PleasanterOutputDir)\ExtendedLibraries にコピーしました"
Importance="high" />
</Target>SkipUnchangedFiles="true" で、変わっていないファイルのコピーは飛ばします。pdb も一緒にコピーしておくと、デバッガがブレークポイントを解決できます。
開発の流れ
図を読み込み中…
差し替えたら必ず再起動
DLL は起動時に Assembly.LoadFrom で読み込まれるだけなので、起動後に ExtendedLibraries の DLL を差し替えても実行中のプロセスには反映されません。ホットリロードも効きません。また読み込みには try-catch が無く、壊れた DLL を置くとプリザンターが起動しなくなります(Startup.cs)。
VS Code でデバッグする
方法 A: 起動中のプリザンターにアタッチする
プリザンターのソースが手元に無くても使えます。
- プリザンターを普通に起動する(
dotnet runやサービス) - 拡張ライブラリのフォルダを VS Code で開き、
.vscode/launch.jsonを作る F5でデバッグを始め、プロセスの一覧からImplem.Pleasanterを選ぶ- 拡張ライブラリのコードにブレークポイントを置き、画面や API から拡張のエンドポイントを呼ぶ
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Pleasanter",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}",
"justMyCode": false,
"symbolOptions": {
"searchPaths": ["${workspaceFolder}/MyExtendedLibrary/bin/Debug/net10.0"]
}
}
]
}シンボルが解決されない(ブレークポイントが白丸のまま)ときは、pdb が ExtendedLibraries に置かれているかを確かめ、そのフォルダも symbolOptions.searchPaths に足します。
方法 B: プリザンターごと起動する
本体のソースが隣にある場合は、マルチルートワークスペースで本体と拡張ライブラリを一緒に開き、F5 一つで「拡張ライブラリのビルド(とコピー)→ プリザンターの起動」まで行えます。毎回アタッチし直す手間がありません。
{
"folders": [
{ "name": "MyExtendedLibrary", "path": "." },
{ "name": "Implem.Pleasanter", "path": "../Implem.Pleasanter" }
],
"settings": {}
}launch.json と tasks.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Pleasanter",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build-extension",
"program": "${workspaceFolder:Implem.Pleasanter}/bin/Debug/net10.0/Implem.Pleasanter.dll",
"args": [],
"cwd": "${workspaceFolder:Implem.Pleasanter}",
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/": "${workspaceFolder:Implem.Pleasanter}"
},
"justMyCode": false,
"symbolOptions": {
"searchPaths": ["${workspaceFolder:Implem.Pleasanter}/bin/Debug/net10.0/ExtendedLibraries"]
}
}
],
"compounds": [
{
"name": "Launch Pleasanter with Extension",
"configurations": ["Launch Pleasanter"]
}
]
}{
"version": "2.0.0",
"tasks": [
{
"label": "build-extension",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/MyExtendedLibrary/MyExtendedLibrary.csproj",
"--configuration",
"Debug"
],
"problemMatcher": "$msCompile",
"group": "build",
"presentation": {
"reveal": "always",
"panel": "new"
}
}
]
}development.code-workspaceを VS Code で開くF5でLaunch Pleasanter with Extensionを選ぶ- 拡張ライブラリがビルドされ、DLL が
ExtendedLibrariesにコピーされたあと、プリザンターが起動して拡張ライブラリを読み込む
本体そのものを VS Code でビルド・起動する準備(DB・接続文字列など)は VS Code だけでビルド・デバッグする環境 を参照してください。
Visual Studio でデバッグする
方法 A: 同じソリューションで起動する
- 拡張ライブラリのソリューションを開き、「追加」→「既存のプロジェクト」で
Implem.Pleasanter.csprojを追加する Implem.Pleasanterを「スタートアップ プロジェクトに設定」する- 拡張ライブラリに上の
CopyToExtendedLibrariesターゲットを入れておく - ブレークポイントを置いて
F5で起動する
MyExtendedLibrary.sln
├── MyExtendedLibrary ← 拡張ライブラリ(クラスライブラリ)
└── Implem.Pleasanter ← 本体(スタートアップ プロジェクト)プリザンターの起動には App_Data/Parameters などが要るため、プロジェクトのプロパティ →「デバッグ」→「作業ディレクトリ」に本体のフォルダを指定します。
方法 B: プロセスにアタッチする
- プリザンターを普通に起動する
- 「デバッグ」→「プロセスにアタッチ」(
Ctrl+Alt+P)を開く - 接続の種類に「マネージド(.NET Core、.NET 5+)」を選び、
Implem.Pleasanterにアタッチする - ブレークポイントを置いて拡張のエンドポイントを呼ぶ
シンボルが見つからないときは、「デバッグ」→「オプション」→「シンボル」で pdb のあるフォルダを追加します。
方法の比較
| VS Code A(アタッチ) | VS Code B(一括起動) | Visual Studio A(同じソリューション) | Visual Studio B(アタッチ) | |
|---|---|---|---|---|
| 本体のソース | 不要 | 必要 | 必要 | 不要 |
| 本体のコードで止める | ソースが無ければ不可 | 可 | 可 | ソースが無ければ不可 |
| 準備の手間 | 少ない | 中 | 中 | 少ない |
| 再起動のたびのアタッチ | 必要 | 不要 | 不要 | 必要 |
| 向いている場面 | すぐ確かめたいとき | 日々の開発 | 本体と一緒に深く追うとき | すぐ確かめたいとき |