Настройка лицензии

Где Doconut ищет ваш файл лицензии

Без лицензии Doconut всё равно отображает документы — каждая страница просто содержит водяной знак оценки. Эта страница описывает четыре способа предоставления лицензии и точный порядок приоритета, когда задано более одного.

Четыре способа предоставления лицензии

Существует четыре: три явных источника в DoconutOptions — поток, необработанное содержимое или путь к файлу — плюс автоматическое обнаружение, когда ни один из них не задан. Когда задано более одного, порядок приоритета ясен:

LicenseStream превалирует над LicenseContent, который превалирует над LicensePath, который превалирует над автоматическим поиском.

По пути

LicensePath передаётся в File.Exists точно так, как указано. Относительный путь разрешается относительно текущего рабочего каталога процесса — а не папки вашего проекта и не папки, в которой находится Program.cs. Если путь не может быть разрешён, Doconut не бросает исключение и не переходит к авто‑поиску — он просто не загружает лицензию, и просмотрщик отображает водяные знаки. Авто‑поиск запускается только когда ни LicensePath, ни LicenseContent, ни LicenseStream не заданы.

Предпочтительно использовать абсолютный путь (например, построенный из IWebHostEnvironment.WebRootPath или AppContext.BaseDirectory), либо полностью опустить LicensePath и полагаться на автоматическое обнаружение ниже.

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

По потоку

LicenseStream читается один раз при запуске — удобно, когда лицензия берётся из хранилища секретов, а не из файла на диске.

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

По содержимому

LicenseContent принимает непосредственно текст лицензии — из переменной окружения, базы данных или менеджера секретов:

csharp
// License XML from a database, environment variable, or secret manager —
 // no file on disk. Beaten only by LicenseStream.
builder.Services.AddDoconut(options =>
{
    options.LicenseContent = Environment.GetEnvironmentVariable("DOCONUT_LICENSE") ?? "";
});

Автоматическое обнаружение

Не задавайте ни один из трёх явных источников, и Doconut самостоятельно ищет лицензию:

csharp
// Configure nothing, and Doconut searches for the license itself:
//   1. {CurrentDirectory}/wwwroot
//   2. {CurrentDirectory}/wwwroot/lib
//   3. AppContext.BaseDirectory  (the build output folder)
// It looks for Doconut.Viewer.lic plus any per-plugin
// Doconut.Viewer.<Capability>.lic files alongside it.
builder.Services.AddDoconut();

Каталоги, проверяемые последовательно, и имена файлов, которые ищутся в каждом из них:

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

Filenames (checked in each directory above, in order):
  Doconut.Viewer.lic                   — base viewer license
  Doconut.Viewer.<Capability>.lic      — per-plugin license, alongside Doconut.Viewer.lic

Скопируйте лицензию в папку вывода

LicensePath и проверка AppContext.BaseDirectory при авто‑поиске оба требуют, чтобы файл .lic находился рядом с собранным приложением — а не только в вашем исходном wwwroot. Тестовое приложение SDK копирует его при каждой сборке с помощью этого MSBuild‑таргета:

xml
<Target Name="CopyLicensesToOutput" AfterTargets="Build">
  <ItemGroup>
    <DoconutLicenseFiles Include="$(MSBuildProjectDirectory)\wwwroot\*.lic" />
  </ItemGroup>
  <Copy SourceFiles="@(DoconutLicenseFiles)" DestinationFolder="$(OutDir)" SkipUnchangedFiles="true" />
</Target>

Держите файлы .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<...>() для этого плагина, либо установить платную лицензию или активную временную/демо‑лицензию (NFR), предоставляющую эту возможность. Временные регистрации могут существовать после даты истечения, чтобы уже настроенное приложение могло работать в ограниченном режиме вместо краша при перезапуске; после истечения их возможности всё равно отзываются.

Проверка загруженной лицензии

Используйте IDoconutLicenseService, тот же источник правды, который использует SDK, чтобы предоставить аутентифицированный диагностический endpoint или управлять флагами функций. Не возвращайте содержимое лицензии или ключи.

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 в настоящее время является совместимым свойством без активного пути перезагрузки, поэтому замена файла лицензии требует перезапуска приложения.

Матрица устранения неполадок

СимптомВероятная причинаПроверка
Просмотрщик работает, но каждая страница имеет водяной знакЛицензия не была загружена, либо её срок по календарю истёкПолучите IDoconutLicenseService; проверьте каталог вывода и текущий рабочий каталог процесса
AddDoconut() бросает исключение для плагинаЛицензия не предоставляет эту возможность плагинаПроверьте IsCapabilityGranted(...) и удалите регистрации, которые вы не приобрели
Настроенный относительный путь работает локально, но не в IIS/контейнереТекущий рабочий каталог процесса изменилсяИспользуйте AppContext.BaseDirectory или абсолютный путь
Замена файла .lic не оказывает эффектаСервис лицензии‑синглтон уже был созданПерезапустите приложение
OpenDocumentAsync бросает LicenseExceptionПодпись, домен, временное окно, чёрный список или проверка во время выполнения плагина отклонили лицензиюПрочитайте сообщение об исключении/отклонении, не раскрывая его ненадёжным клиентам

Следующие шаги

  • Лицензирование — возможности, уровни лицензий и проверка того, что было загружено во время выполнения.
  • Устранение неполадок — водяные знаки, отклонённые лицензии и ошибки возможностей.

Была ли эта страница полезной?