COM/ActiveX

O DotNetBrowser não suporta a exposição da sua funcionalidade como componentes COM ou controles ActiveX prontos para utilizar.

No entanto, se precisar integrar o DotNetBrowser com uma aplicação capaz de trabalhar apenas com OLE/COM/ActiveX, você pode considerar envolver a funcionalidade que necessita e, em seguida, expor esses wrappers a essa aplicação. Tanto o .NET Framework como as versões mais recentes do .NET (a partir do .NET Core 3.0) têm suporte para interoperar com bibliotecas COM. Como resultado, toda a funcionalidade do Chromium fornecida pelo DotNetBrowser pode ser acessada no VB6, VBA, VBScript, etc.

Eis a descrição geral da ideia:

  1. Desenvolva e declare um conjunto de interfaces COM que exponham a funcionalidade de que necessita. Estas interfaces podem ser colocadas em um projeto separado. Utilize o atributo ComVisible para controlar a acessibilidade de determinadas classes e interfaces.
  2. Nas implementações dessas interfaces, inicialize o DotNetBrowser e execute todas as ações necessárias.
  3. Se necessário, personalize o registro da montagem utilizando os atributos ComRegisterFunction e ComUnregisterFunction. Isto pode parecer necessário se planeja registrar um controle ActiveX baseado nas capacidades do DotNetBrowser.
  4. Construa a montagem e registre-o utilizando a ferramenta de registro de montagens (regasm.exe).

Depois disso, as entradas correspondentes aparecerão no registro do Windows e o wrapper ficará disponível para os clientes COM.

O código do exemplo de projeto que envolve a funcionalidade DotNetBrowser e a expõe a clientes COM está disponível no repositório GitHub como projetos Visual Studio: C#, VB.NET

A seção seguinte analisa a implementação e explica as partes mais importantes do exemplo.

Implementação

Declarando interfaces COM

Existem algumas formas de declarar interfaces COM no .NET. Por exemplo, você pode considerar a utilização do atributo ClassInterface numa classe para expor todos os seus métodos públicos, propriedades, campos e eventos a clientes COM. No exemplo, uma abordagem diferente é utilizada - todo a montagem é marcada como ComVisible, e as interfaces são declaradas explicitamente e tornadas públicas. Esta abordagem pode ajudar a obter um melhor controle sobre o que é exatamente exposto à COM. As implementações de interface são declaradas como classes internas. Por exemplo:

Interface:

[Guid("D620EC2F-03E8-4C1A-9FF9-3A7B44590F54")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IComEngine
{
    [DispId(1)]
    void Initialize();

    [DispId(2)]
    void Dispose();

    [DispId(3)]
    IComBrowser CreateBrowser();
}

Esta interface de exemplo fornece três métodos - dois deles podem ser utilizados para controlar o tempo de vida da instância IEngine e o terceiro é utilizado para criar uma instância IBrowser e devolver o invólucro COM correspondente ao cliente.

Você pode também considerar a aplicação do atributo ComVisible a classes e interfaces específicas em vez de o aplicar a todo o conjunto. Neste caso, apenas as classes e interfaces marcadas com este atributo estarão disponíveis para os clientes COM. Todos os outros tipos públicos não serão expostos.

Implementação de interfaces COM

Eis um exemplo de implementação da interface mencionada na seção anterior:

Implementação:

[Guid("DAE7A4AC-2D70-4830-81D8-3D7E5D8A7981")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("DotNetBrowser.ComWrapper.Engine")]
public class EngineWrapper : IComEngine
{
    private IEngine engine;
    private bool initialized;

    #region Methods

    public IComBrowser CreateBrowser() => new BrowserImpl(engine.CreateBrowser());

    public void Dispose()
    {
        if (initialized)
        {
            engine?.Dispose();
            engine = null;
            initialized = false;
        }
    }

    public void Initialize()
    {
        if (!initialized)
        {
            engine = EngineFactory.Create(new EngineOptions.Builder
            {
                RenderingMode = RenderingMode.OffScreen
            }.Build());
            initialized = true;
        }
    }

    #endregion
}

Neste exemplo, a implementação é pública e tem um ProgID especificado - como resultado, a coclasse correspondente será exposta a COM e o ProgID será utilizado para a referenciar.

Personalização do registro de montagem

O projeto de exemplo também fornece a classe ComBrowserView - um invólucro para o WinForms BrowserView que pode ser utilizado como um controle ActiveX independente. Para o tornar reconhecível como um controle ActiveX, é necessário adicionar algumas entradas de registro personalizadas durante o registro do tipo correspondente. Isto pode ser feito definindo dois métodos estáticos na classe ComBrowserView e aplicando-lhes os atributos ComRegisterFunction e ComUnregisterFunction:

public partial class ComBrowserView : UserControl, IComBrowserView
{
    // ...

    [EditorBrowsable(EditorBrowsableState.Never)]
    [ComRegisterFunction]
    private static void Register(Type t)
    {
        ControlRegistration.RegisterControl(t);
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    [ComUnregisterFunction]
    private static void Unregister(Type t)
    {
        ControlRegistration.UnregisterControl(t);
    }
}

A implementação ControlRegistration.RegisterControl adiciona algumas subchaves à chave de registro CLSID correspondente - a mais significativa é a chave Control, que permite que o controle personalizado apareça no contêiner de controles ActiveX. As outras subchaves definem a abordagem de ativação do controle que deve ser utilizada, o ícone da caixa de ferramentas, o GUID da biblioteca de tipos, etc.

Construindo o projeto e registrar a montagem

Para registrar o conjunto durante a construção, a opção “Register for COM Interop” é ativada no projeto de exemplo. Isto pode parecer útil para depurar a implementação.

Como resultado, a TLB é gerada e registrada automaticamente. A limpeza do projeto leva à anulação do registro de todos os componentes.

Verifique os bits da aplicação com a qual está tentando se integrar. Se a sua aplicação for de 64 bits e o controle estiver registrado apenas para aplicações de 32 bits (neste caso, as entradas de registro são criadas em HKEY_CLASSES_ROOT\WOW6432Node\), o controle ficará inacessível para esta aplicação. O mesmo pode ser observado se a aplicação for de 32 bits e o controle for registrado apenas para aplicações de 64 bits.

Resumo

A abordagem descrita pode parecer útil para criar as soluções que fornecem a funcionalidade baseada no Chromium às aplicações que utilizam objetos COM ou incorporam controles ActiveX.

Go Top