ライセンス設定

Doconut がライセンスファイルを探す場所

ライセンスがなくても、Doconut はドキュメントをレンダリングしますが、各ページには評価用の透かしが表示されます。このページでは、ライセンスを提供する4つの方法と、複数設定された場合の正確な優先順位について説明します。

ライセンスは AddDoconut() の実行時に一度だけ 読み込まれます。これは、以前の .NET Standard ライブラリでは、Viewer インスタンスにライセンスを渡すか、静的メソッド Viewer.DoconutLicense(...) / Viewer.SetLicensePlugin(...) を使用して設定していたのとは異なります。このリリースではそれらのメソッドは起動時のメカニズムではなくなっています — マイグレーションガイド を参照してください。

ライセンスを提供する4つの方法

Doconut には4つの方法があります。DoconutOptions で指定できる明示的なソースは3つ(ストリーム、RAW コンテンツ、ファイルパス)で、どれも設定しない場合は自動検出が行われます。複数が設定されている場合の優先順位は次のとおりです。

LicenseStream が LicenseContent を、LicenseContent が LicensePath を、LicensePath が自動検索を上回ります。
(LicenseStream > LicenseContent > LicensePath > auto-search)

パスで指定

LicensePath はそのまま File.Exists に渡されます。相対パスはプロセスの 現在の作業ディレクトリ を基準に解決されます — プロジェクトフォルダや Program.cs があるフォルダではありません。パスが解決できない場合、Doconut は例外をスローせず、自動検索にフォールバックもしません — 単にライセンスがロードされず、ビューアに透かしが表示されます。自動検索は LicensePath、LicenseContent、LicenseStream のいずれも設定されていないときにのみ実行されます。同じフォルダにあるプラグインごとのライセンスファイル(Doconut.Viewer.<Capability>.lic)もこれと共に読み込まれるため、プラグインのライセンスがベースライセンスと同じ場所にある場合、LicensePath と AddPlugin<...>() は連携して動作します。

絶対パスを使用することを推奨します(例:IWebHostEnvironment.WebRootPath や AppContext.BaseDirectory から構築)。あるいは LicensePath を完全に省略し、以下の自動検出に任せても構いません。

csharp
builder.Services.AddDoconut(options =>
{
    options.LicensePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", "Doconut.Viewer.lic");
});

ストリームで指定

LicenseStream は起動時に一度だけ読み取られます — ライセンスがディスク上のファイルではなくシークレットストアから取得される場合に便利です。

csharp
// 優先順位: LicenseStream > LicenseContent > LicensePath > auto-search.
builder.Services.AddDoconut(options =>
{
    options.LicenseStream = licenseStream;
});

コンテンツで指定

LicenseContent はライセンス文字列そのものを受け取ります — 環境変数、データベース、またはシークレットマネージャから取得できます。

csharp
// データベース、環境変数、またはシークレットマネージャから取得したライセンス XML —
// ディスク上のファイルは使用しません。LicenseStream にのみ上回られます。
builder.Services.AddDoconut(options =>
{
    options.LicenseContent = Environment.GetEnvironmentVariable("DOCONUT_LICENSE") ?? "";
});

自動検出

3つの明示的なソースをすべて設定しないと、Doconut が自動的にライセンスを検索します:

csharp
// 何も設定しない場合、Doconut は以下の2つのフォルダのみでライセンスを自動検索します:
//   1. {CurrentDirectory}/wwwroot
//   2. {AppContext.BaseDirectory}/wwwroot   (ビルド出力フォルダ内の wwwroot)
// まず Doconut.lic を探し、次に Doconut.Viewer.lic、さらに各機能ごとの
// Doconut.Viewer.<Capability>.lic ファイルをそれに隣接して探します。
builder.Services.AddDoconut();

検索対象フォルダ(順序)と各フォルダで探すファイル名は以下の通りです:

text
1. {CurrentDirectory}/wwwroot
2. {AppContext.BaseDirectory}/wwwroot

ファイル名(上記各フォルダで順にチェック):
  Doconut.lic                          — 基本ビューアライセンス(最初にチェック)
  Doconut.Viewer.lic                   — 基本ビューアライセンス
  Doconut.Viewer.<Capability>.lic      — 機能ごとのライセンス、基本ライセンスと同じ場所にあります

wwwroot フォルダ外のファイルは読み取られません。出力フォルダ直下や wwwroot/lib にある .lic は無視されます。

以前に Viewer コンストラクタに List<string> でライセンスパス(機能ごとに1つ)を渡していた場合は、Doconut.Viewer.lic の隣にそれらの補助ファイルを配置し、自動検出に拾わせてください。DoconutOptions にはパスのリストを指定するオプションはありません。

ライセンスを出力フォルダーにコピーする

プロセスがプロジェクト フォルダーから実行されない場合(公開アプリ、IIS、コンテナ、テスト ランナーなど)には、最初の探索が失敗し、2 番目の探索である {AppContext.BaseDirectory}/wwwroot がファイルを探す必要があります。SDK のテスト アプリは、ビルドのたびにこの MSBuild ターゲットでライセンスをそこにコピーします。

xml
<Target Name="CopyLicensesToOutput" AfterTargets="Build">
  <ItemGroup>
    <DoconutLicenseFiles Include="$(MSBuildProjectDirectory)\wwwroot\*.lic" />
    <StaleOutputLicenses Include="$(OutDir)wwwroot\*.lic" />
  </ItemGroup>
  <!-- 最初に削除します。これにより wwwroot 内の .lic を名前変更または削除した場合も出力から除外されます。 -->
  <Delete Files="@(StaleOutputLicenses)" />
  <Copy SourceFiles="@(DoconutLicenseFiles)" DestinationFolder="$(OutDir)wwwroot" />
</Target>

出力先は $(OutDir)wwwroot である必要があります。.lic を出力ルートにコピーしても自動検索では見つかりません。このページの LicensePath の例も同じ場所を指しています。

.lic ファイルはソース管理に含めないでください。アプリと同じ場所にデプロイするか、シークレット ストアから LicenseContent または LicenseStream を使用してライセンスを注入してください。

ライセンスがない場合に何が起こるか

ライセンスが存在しなくても例外はスローされません。AddDoconut() は成功し、アプリが起動し、ビューアが実行されますが、すべてのページに評価用の透かしが付与され、オプション機能は一切利用できません。

ライセンス ファイルが見つかったものの拒否された場合は別です。署名が無効、改ざん、ブラックリスト登録、またはライセンスのバージョン ウィンドウ外でビルドされた場合、OpenDocumentAsync は LicenseException をスローし、License.RejectionMessage に理由が格納されます。拒否メッセージが無いカレンダー期限切れのライセンスは、透かし付きモードで継続します。

プラグインには機能が必要です

対応する権利が付与されていないプラグインを登録すると、状況が異なります。ライセンスがない場合、レガシーな TRIAL ファイルがある場合、またはその機能を持たない有料ライセンスの場合、AddDoconut() は InvalidOperationException をスローし、アプリは起動しません。例として、Converter 機能を付与するライセンスがない状態で Converter プラグインを登録した場合を示します。

text
InvalidOperationException: The Converter plugin is registered via AddPlugin but no active
license grants Converter. Remove the AddPlugin<...>() call or install a license (or
trial/demo) that includes Converter.

メッセージは直接的に解決策を示しています。対象プラグインの options.AddPlugin<...>() 呼び出しを削除するか、機能を付与する有料ライセンスまたは有効な Temporary/Demo(NFR)ライセンスをインストールしてください。Temporary 登録は有効期限が過ぎても残り、再起動時にクラッシュせずにランタイムで機能が低下します。期限が切れた後も機能は取り消されます。

読み込まれたライセンスを検証する

SDK と同じ真実の情報源である IDoconutLicenseService を使用して、認証済み診断エンドポイントを公開したり、機能フラグを制御したりします。ライセンスの内容やキーを返さないでください。

csharp
app.MapGet("/api/doconut/license", (IDoconutLicenseService license) => Results.Ok(new
{
    viewer = license.IsViewerLicensed || license.IsTemporary,
    temporary = license.IsTemporary,
    search = license.IsCapabilityGranted(LicenseCapability.Search),
    annotation = license.IsCapabilityGranted(LicenseCapability.Annotation),
    converter = license.HasConverter,
    dicom = license.HasDicom
}));

ライセンスは AddDoconut() の登録時に読み込まれます。ResetLicense は現在互換性のためのプロパティで、アクティブなリロード パスはありません。そのため、ライセンス ファイルを差し替える場合はアプリケーションを再起動する必要があります。

トラブルシューティングマトリックス

症状考えられる原因確認事項
Viewer が動作するがすべてのページに透かしが入るライセンスが読み込まれていない、またはライセンスが期限切れ(カレンダー期限)IDoconutLicenseService を解決し、出力ディレクトリとプロセスの作業ディレクトリを確認する
AddDoconut() がプラグインで例外をスローするライセンスがそのプラグイン機能を付与していないIsCapabilityGranted(...) を確認し、購入していない登録を削除する
設定された相対パスはローカルでは動作するが IIS/コンテナでは動作しないプロセスの作業ディレクトリが変更されたAppContext.BaseDirectory または絶対パスを使用する
置き換えた .lic ファイルに効果がないシングルトンのライセンスサービスがすでに作成されているアプリケーションを再起動する
OpenDocumentAsync が LicenseException をスローする署名、ドメイン、バージョンウィンドウ、ブラックリスト、またはプラグイン実行時ゲートがライセンスを拒否した例外/拒否メッセージを読み取るが、信頼できないクライアントに公開しない
機能別ライセンスは以前は動作したが現在は動作しない旧コードが Viewer コンストラクタに明示的なライセンスパスを渡していた関連する .lic ファイルを Doconut.Viewer.lic の隣に配置し、自動検出に任せる

次のステップ

このページは役に立ちましたか?