Configuração de Licença
Onde o Doconut procura seu arquivo de licença
Sem uma licença, o Doconut ainda renderiza documentos — cada página apenas exibe uma marca d'água de avaliação. Esta página cobre as quatro maneiras de fornecer uma licença e a precedência exata quando mais de uma está definida.
Quatro maneiras de fornecer uma licença
Existem quatro: três fontes explícitas em DoconutOptions — um stream, conteúdo bruto ou um caminho de arquivo — além da descoberta automática quando nenhuma delas está definida. Quando mais de uma está definida, a precedência é exata:
LicenseStream supera LicenseContent supera LicensePath supera pesquisa automática.
Por caminho
LicensePath é passado para File.Exists exatamente como fornecido. Um caminho relativo é resolvido em relação ao diretório de trabalho atual do processo — não à pasta do seu projeto, e não à pasta onde o Program.cs está. Se o caminho não for resolvido, o Doconut não lança exceção e não recorre à busca automática — ele simplesmente não carrega nenhuma licença e o visualizador exibe a marca d'água. A busca automática só é executada quando nenhum de LicensePath, LicenseContent ou LicenseStream está definido. Os arquivos de licença por plugin na mesma pasta (Doconut.Viewer.<Capability>.lic) são lidos com ela, de modo que LicensePath e AddPlugin<...>() funcionam juntos quando as licenças dos plugins ficam ao lado da licença base.
Prefira um caminho absoluto (por exemplo construído a partir de IWebHostEnvironment.WebRootPath ou AppContext.BaseDirectory), ou omita LicensePath completamente e confie na descoberta automática abaixo.
builder.Services.AddDoconut(options =>
{
options.LicensePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", "Doconut.Viewer.lic");
});Por stream
LicenseStream é lido uma única vez na inicialização — útil quando a licença vem de um armazenamento secreto em vez de um arquivo no disco.
// Precedência: LicenseStream > LicenseContent > LicensePath > pesquisa automática.
builder.Services.AddDoconut(options =>
{
options.LicenseStream = licenseStream;
});Por conteúdo
LicenseContent aceita o próprio texto da licença — de uma variável de ambiente, de um banco de dados ou de um gerenciador de segredos:
// XML da licença de um banco de dados, variável de ambiente ou gerenciador de segredos —
// sem arquivo no disco. Superada apenas por LicenseStream.
builder.Services.AddDoconut(options =>
{
options.LicenseContent = Environment.GetEnvironmentVariable("DOCONUT_LICENSE") ?? "";
});Descoberta automática
Não configure nenhuma das três fontes explícitas, e o Doconut procura a licença por conta própria:
// Não configure nada, e o Doconut procura a licença por conta própria, apenas nestas duas pastas:
// 1. {CurrentDirectory}/wwwroot
// 2. {AppContext.BaseDirectory}/wwwroot (wwwroot dentro da pasta de saída da compilação)
// Ele procura por Doconut.lic primeiro, depois Doconut.Viewer.lic, além de qualquer
// arquivos Doconut.Viewer.<Capability>.lic ao lado dele.
builder.Services.AddDoconut();As pastas de sondagem, em ordem, e os nomes de arquivos procurados em cada uma:
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 licenseNada fora de uma pasta wwwroot é lido: um .lic na própria pasta de saída, ou em wwwroot/lib, é ignorado.
Copie a licença para sua pasta de saída
Quando o processo não é executado a partir da pasta do projeto — um aplicativo publicado, IIS, um contêiner, um executor de testes — a primeira sondagem falha, e a segunda, {AppContext.BaseDirectory}/wwwroot, precisa encontrar o arquivo. O próprio aplicativo de teste do SDK copia as licenças para lá em cada compilação com este alvo MSBuild:
<Target Name="CopyLicensesToOutput" AfterTargets="Build">
<ItemGroup>
<DoconutLicenseFiles Include="$(MSBuildProjectDirectory)\wwwroot\*.lic" />
<StaleOutputLicenses Include="$(OutDir)wwwroot\*.lic" />
</ItemGroup>
<!-- Delete first, so renaming or removing a .lic in wwwroot also takes it out of the output. -->
<Delete Files="@(StaleOutputLicenses)" />
<Copy SourceFiles="@(DoconutLicenseFiles)" DestinationFolder="$(OutDir)wwwroot" />
</Target>O destino deve ser $(OutDir)wwwroot: um .lic copiado para a raiz da saída nunca é encontrado pela busca automática. Os exemplos de LicensePath nesta página apontam para o mesmo local.
Mantenha os arquivos
.licfora do controle de versão — implante-os ao lado do aplicativo, ou injete a licença através deLicenseContentouLicenseStreama partir do seu armazenamento secreto.
O que acontece sem uma licença
Uma licença ausente não gera exceção. AddDoconut() tem sucesso, o aplicativo inicia e o visualizador funciona — mas cada página exibe uma marca d'água de avaliação e nenhuma capacidade opcional é concedida.
Um arquivo de licença que é encontrado, mas rejeitado, é diferente. Uma assinatura inválida, adulteração, inclusão em lista negra ou uma compilação fora da janela de versão da licença faz com que OpenDocumentAsync lance LicenseException com License.RejectionMessage. Uma licença expirada por calendário que não possui mensagem de rejeição continua no modo com marca d'água.
Plugins precisam de capacidades
Registrar um plugin sem a concessão correspondente é diferente: para uma licença ausente, um arquivo legado TRIAL ou uma licença paga sem aquela capacidade, AddDoconut() lança InvalidOperationException, de modo que o aplicativo não inicia. Por exemplo, registrar o plugin Converter sem uma licença que conceda 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.A mensagem indica a correção diretamente: remova a chamada options.AddPlugin<...>() para esse plugin ou instale uma licença paga ou uma licença Temporária/Demo (NFR) ativa que conceda a capacidade. Registros temporários podem sobreviver à data de expiração, permitindo que um aplicativo já configurado degrade em tempo de execução em vez de travar durante a reinicialização; uma vez expiradas, suas capacidades ainda são revogadas.
Verificar a licença carregada
Use IDoconutLicenseService, a mesma fonte de verdade usada pelo SDK, para expor um endpoint de diagnóstico autenticado ou para controlar flags de recursos. Não retorne o conteúdo da licença nem as chaves.
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
}));A licença é lida durante o registro AddDoconut(). ResetLicense é atualmente uma propriedade de compatibilidade sem caminho de recarregamento ativo, portanto substituir um arquivo de licença requer reiniciar a aplicação.
Matriz de solução de problemas
| Sintoma | Causa provável | Verificação |
|---|---|---|
| O visualizador funciona, mas cada página tem marca d'água | Nenhuma licença foi carregada, ou a licença está expirada por calendário | Resolva IDoconutLicenseService; verifique o diretório de saída e o diretório de trabalho do processo |
AddDoconut() lança exceção para um plugin | A licença não concede a capacidade desse plugin | Verifique IsCapabilityGranted(...) e remova registros que você não comprou |
| Um caminho relativo configurado funciona localmente, mas não no IIS/contêiner | O diretório de trabalho do processo mudou | Use AppContext.BaseDirectory ou um caminho absoluto |
Arquivo .lic substituído não tem efeito | O serviço singleton de licença já havia sido criado | Reinicie o aplicativo |
OpenDocumentAsync lança LicenseException | Assinatura, domínio, janela de versão, lista negra ou verificação em tempo de execução do plugin rejeitaram a licença | Leia a mensagem de exceção/rejeição sem expô-la a clientes não confiáveis |
Próximos passos
- Licenciamento — capacidades, níveis de licença e verificação do que foi carregado em tempo de execução.
- Solução de problemas — marcas d'água, licenças rejeitadas e erros de capacidade.
Esta página foi útil?