Настройка лицензии
Где Doconut ищет ваш файл лицензии
Без лицензии Doconut всё равно отображает документы — каждая страница просто содержит водяной знак оценки. Эта страница описывает четыре способа предоставления лицензии и точный порядок приоритета, когда задано более одного.
Четыре способа предоставить лицензию
Существует четыре: три явных источника на DoconutOptions — поток, необработанное содержимое или путь к файлу — плюс автоматическое обнаружение, когда ни один из них не задан. Когда задано более одного, порядок приоритета точный:
LicenseStream побеждает LicenseContent побеждает LicensePath побеждает авто‑поиск.
По пути
LicensePath передаётся в File.Exists точно так, как указано. Относительный путь разрешается относительно текущего рабочего каталога процесса — а не вашей папки проекта и не папки, в которой находится Program.cs. Если путь не разрешается, Doconut не бросает исключение и не переходит к автоматическому поиску — он просто не загружает лицензию, и просмотрщик отображает водяные знаки. Автоматический поиск запускается только когда ни LicensePath, ни LicenseContent, ни LicenseStream не заданы. Файлы лицензий плагинов в той же папке (Doconut.Viewer.<Capability>.lic) читаются вместе с ним, поэтому LicensePath и AddPlugin<...>() работают совместно, когда лицензии плагинов находятся рядом с основной лицензией.
Предпочтительно использовать абсолютный путь (например, построенный из IWebHostEnvironment.WebRootPath или AppContext.BaseDirectory), либо полностью пропустить LicensePath и полагаться на автоматическое обнаружение ниже.
builder.Services.AddDoconut(options =>
{
options.LicensePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", "Doconut.Viewer.lic");
});По потоку
LicenseStream читается один раз при запуске — это полезно, когда лицензия берётся из секретного хранилища, а не из файла на диске.
// Приоритет: LicenseStream > LicenseContent > LicensePath > авто‑поиск.
builder.Services.AddDoconut(options =>
{
options.LicenseStream = licenseStream;
});По содержимому
LicenseContent принимает сам текст лицензии — из переменной окружения, базы данных или менеджера секретов:
// License XML из базы данных, переменной окружения или менеджера секретов —
// нет файла на диске. Уступает только LicenseStream.
builder.Services.AddDoconut(options =>
{
options.LicenseContent = Environment.GetEnvironmentVariable("DOCONUT_LICENSE") ?? "";
});Автоматическое обнаружение
Не задавайте ни один из трёх явных источников, и Doconut самостоятельно ищет лицензию:
// Не настраивая ничего, Doconut ищет лицензию сам, только в этих двух папках:
// 1. {CurrentDirectory}/wwwroot
// 2. {AppContext.BaseDirectory}/wwwroot (wwwroot внутри папки вывода сборки)
// Сначала ищет Doconut.lic, затем Doconut.Viewer.lic, плюс любые per-plugin
// файлы Doconut.Viewer.<Capability>.lic рядом с ним.
builder.Services.AddDoconut();Папки для поиска, в порядке приоритета, и имена файлов, которые проверяются в каждой:
1. {CurrentDirectory}/wwwroot
2. {AppContext.BaseDirectory}/wwwroot
Filenames (checked in each folder above, in order):
Doconut.lic — base viewer license (checked first)
Doconut.Viewer.lic — base viewer license
Doconut.Viewer.<Capability>.lic — per-plugin license, alongside the base licenseНичего за пределами папки wwwroot не читается: .lic в самой папке вывода или в wwwroot/lib игнорируется.
Скопируйте лицензию в папку вывода
Когда процесс не запускается из папки проекта — опубликованное приложение, IIS, контейнер, тестовый раннер — первый поиск не находит файл, и второй, {AppContext.BaseDirectory}/wwwroot, должен найти его. Тестовое приложение SDK копирует лицензии туда при каждой сборке с помощью этой цели MSBuild:
<Target Name="CopyLicensesToOutput" AfterTargets="Build">
<ItemGroup>
<DoconutLicenseFiles Include="$(MSBuildProjectDirectory)\wwwroot\*.lic" />
<StaleOutputLicenses Include="$(OutDir)wwwroot\*.lic" />
</ItemGroup>
<!-- Сначала удалите, чтобы переименование или удаление .lic в wwwroot также исключало его из вывода. -->
<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:
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, чтобы предоставить аутентифицированный диагностический эндпоинт или управлять флагами функций. Не возвращайте содержимое лицензии или ключи.
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 | Подпись, домен, окно версии, черный список или проверка времени выполнения плагина отклонили лицензию | Прочитайте сообщение об исключении/отклонении, не раскрывая его недоверенным клиентам |
Следующие шаги
- Лицензирование — возможности, уровни лицензий и проверка того, что было загружено во время выполнения.
- Устранение неполадок — водяные знаки, отклонённые лицензии и ошибки возможностей.
Была ли эта страница полезной?