Configuração de Licença

Onde 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.

A licença é carregada uma vez, durante AddDoconut(). Isso é uma mudança em relação à biblioteca .NET Standard anterior, onde a licença era passada para uma instância Viewer ou definida através das chamadas estáticas Viewer.DoconutLicense(...) / Viewer.SetLicensePlugin(...). Esses métodos não são um mecanismo de inicialização nesta versão — veja o guia de migração.

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 tem prioridade sobre LicenseContent tem prioridade sobre LicensePath tem prioridade sobre busca 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 junto, 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.

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

Por stream

LicenseStream é lido uma vez na inicialização — útil quando a licença vem de um armazenamento secreto em vez de um arquivo no disco.

csharp
// Precedência: LicenseStream > LicenseContent > LicensePath > busca 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:

csharp
// XML de licença de um banco de dados, variável de ambiente ou gerenciador de segredos —
// sem arquivo no disco. Superado apenas por LicenseStream.
builder.Services.AddDoconut(options =>
{
    options.LicenseContent = Environment.GetEnvironmentVariable("DOCONUT_LICENSE") ?? "";
});

Descoberta automática

Configure nenhuma das três fontes explícitas, e Doconut procura a licença por conta própria, apenas nestas duas pastas:

csharp
// Não configure nada, e 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 de compilação)
// Ele procura primeiro por Doconut.lic, depois Doconut.Viewer.lic, além de quaisquer licenças por capacidade
// Doconut.Viewer.<Capability>.lic ao lado dela.
builder.Services.AddDoconut();

As pastas de sondagem, em ordem, e os nomes de arquivos procurados em cada uma:

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

Nomes de arquivos (verificados em cada pasta acima, em ordem):
  Doconut.lic                          — licença base do visualizador (verificada primeiro)
  Doconut.Viewer.lic                   — licença base do visualizador
  Doconut.Viewer.<Capability>.lic      — licença por capacidade, ao lado da licença base

Nada fora de uma pasta wwwroot é lido: um .lic na própria pasta de saída, ou em wwwroot/lib, é ignorado.

Se você anteriormente passou um List<string> de caminhos de licença para o construtor Viewer — um por capacidade — mantenha esses arquivos acompanhantes ao lado de Doconut.Viewer.lic e deixe a descoberta automática capturá‑los. Não há opção de lista de caminhos em DoconutOptions.

Copie a licença para a 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 tentativa falha, e a segunda, {AppContext.BaseDirectory}/wwwroot, precisa encontrar o arquivo. O aplicativo de teste próprio do SDK copia as licenças para lá em cada compilação com este alvo MSBuild:

xml
<Target Name="CopyLicensesToOutput" AfterTargets="Build">
  <ItemGroup>
    <DoconutLicenseFiles Include="$(MSBuildProjectDirectory)\wwwroot\*.lic" />
    <StaleOutputLicenses Include="$(OutDir)wwwroot\*.lic" />
  </ItemGroup>
  <!-- Exclua primeiro, para que renomear ou remover um .lic em wwwroot também o remova da saída. -->
  <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 pesquisa automática. Os exemplos de LicensePath nesta página apontam para o mesmo local.

Mantenha os arquivos .lic fora do controle de versão — implante‑os ao lado do aplicativo, ou injete a licença através de LicenseContent ou LicenseStream a 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, 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 expirado por calendário que não tem mensagem de rejeição continua no modo com marca d'água.

Plugins precisam de capacidades

Registrar um plugin sem a correspondente permissão é 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:

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.

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 são permitidos a sobreviver à data de expiração para que um aplicativo já configurado possa degradar em tempo de execução em vez de falhar na reinicialização; uma vez expiradas, suas capacidades ainda são revogadas.

Verifique a licença carregada

Use IDoconutLicenseService, a mesma fonte de verdade usada pelo SDK, para expor um endpoint diagnóstico autenticado ou para conduzir bandeiras de recursos. Não retorne o conteúdo da licença ou chaves.

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
}));

A licença é lida durante o registro AddDoconut(). ResetLicense é atualmente uma propriedade de compatibilidade sem caminho ativo de recarregamento, portanto substituir um arquivo de licença requer reiniciar a aplicação.

Matriz de solução de problemas

SintomaCausa provávelVerificação
O visualizador funciona, mas cada página tem marca d'águaNenhuma licença foi carregada, ou a licença está expirado por calendárioResolva IDoconutLicenseService; verifique o diretório de saída e o diretório de trabalho do processo
AddDoconut() lança exceção para um pluginA licença não concede a capacidade desse pluginVerifique IsCapabilityGranted(...) e remova registros que você não comprou
Um caminho relativo configurado funciona localmente, mas não no IIS/contêinerO diretório de trabalho do processo mudouUse AppContext.BaseDirectory ou um caminho absoluto
Arquivo .lic substituído não tem efeitoO serviço singleton de licença já foi criadoReinicie a aplicação
OpenDocumentAsync lança LicenseExceptionAssinatura, domínio, janela de versão, lista negra ou verificação de tempo de execução do plugin rejeitaram a licençaLeia a mensagem de exceção/rejeição sem expô‑la a clientes não confiáveis
Uma licença por capacidade funcionava antes, mas não agoraO código antigo passava caminhos de licença explícitos ao construtor ViewerMova os arquivos .lic acompanhantes ao lado de Doconut.Viewer.lic e deixe a descoberta automática carregá‑los

Próximos passos

  • Licenciamento — recursos, 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 recursos.

Esta página foi útil?