Compartilhar via


Solucionando problemas de interoperabilidade (Visual Basic)

Quando você interoperabilidade entre código gerenciado do e COM o .NET Framework, você pode encontrar um ou mais dos seguintes problemas comuns.

Interop Marshaling

Às vezes, talvez você precise usar tipos de dados que não são parte do .NET Framework. Assemblies de interoperabilidade lidar com a maior parte do trabalho para objetos COM , mas talvez você precise controlar os tipos de dados que são usados quando os objetos gerenciado são expostos a COM. Por exemplo, estruturas de bibliotecas de classe devem especificar o BStr um tipo não gerenciado em cadeias de caracteres enviada para objetos COM criados pelo Visual Basic 6.0 e versões anteriores. Em tais casos, você pode usar o MarshalAsAttribute atributo para fazer com que tipos de gerenciado ser exposto como de tipos não gerenciados.

Exportando fixo seqüências de comprimento gerenciado para Códigode-

No Visual Basic 6.0 e versões anteriores, seqüências de caracteres são exportadas para objetos COM como seqüências de bytes sem um caractere de terminação nula. Para compatibilidade com outros idiomas, Visual Basic 2005 inclui um caractere de finalização ao exportar seqüências de caracteres. É a melhor maneira de resolver essa incompatibilidade de cadeias de caracteres exportar que falta o caractere de finalização como matrizes de Byte ou Char.

Exportação de hierarquias de herança

Hierarquias de classe de gerenciada nivelar quando expostos como objetos COM . Por exemplo, se você define uma classe base com um membro e, em seguida, herda a classe base em uma classe derivada que é exposto como umobjetodo COM, os clientes que usam a classe derivada doobjeto do COMnão poderão usar os membros herdados. Os membros de classe de base podem ser acessados a partir de objetos COM somente como instâncias de uma classe basee somente se a classe base também é criado como umobjetodo COM.

Métodos sobrecarregados

Embora você possa criar sobrecarregado métodos com Visual Basic, eles não são suportados pelo COM. Quando uma classe que contém métodos sobrecarregados é exposta como umobjetodo COM, os novos nomes de método são gerados para métodos sobrecarregados.

Por exemplo, considere uma classe que tem duas sobrecargas da Synch método. Quando a classe é exposta como umobjetodo COM, os novos nomes de método de gerado poderiam ser Synch e Synch_2.

A renomeação pode causar problemas de dois para consumidores do COM objeto.

  1. Clientes não podem esperar que os nomes de método de gerado.

  2. Os nomes de método de gerado na classe exposto como umobjeto do COMpode alterar quando novas sobrecargas são adicionadas à classe ou sua classe base. Isso pode causar problemas de versionamento.

Para solucionar os dois problemas, dar a cada método um nome exclusivo, em vez de usar a sobrecarga, quando você desenvolve objetos que serão expostos como objetos COM .

Uso de objetos COM Assemblies de interoperabilidade

Você pode usar assemblies de interoperabilidade como se eles são substituições de código gerenciado para os objetos COM que eles representam. No entanto, porque eles são invólucros e COM , existem algumas diferenças entre usar assemblies de interoperabilidade e conjuntos de módulos padrão. Essas áreas de diferença incluem a exposição de classes e tipos de dados para parâmetros e valores de retorno.

Classes expostas como ambas as Interfaces e Classes

Diferentemente das classes em conjuntos de módulos padrão, classes COM são expostas em assemblies de interoperabilidade como uma interface e uma classe que representa aclassedo COM. Nome da interfaceé idêntico daclassede COM. O nome da classe de interoperabilidade é o mesmo da original COM classe, mas com a palavra "Class" acrescentado. Por exemplo, suponha que você tenha um projeto com uma referência a um assembly de interoperabilidade para umobjetodo COM. Se aclasse do COMé chamado MyComClass, IntelliSense e Pesquisador de Objetos mostram uma interface denominada MyComClass e uma classe nomeada MyComClassClass.

A criação de instâncias de um.NET Framework "crua"

Em geral, se criar uma instância de um .NET Frameworkclasse usando o Newademonstrativo com um nome de classe . Tendo uma COMaclasse representada por um assembly de interoperabilidade é o único caso em que você pode usar o Newademonstrativo com uma interface. A menos que você estiver usando aclasse COMum Inheritsdedemonstrativo, você pode usar a interface como faria com uma classe. O código a seguir demonstra como criar um Commandoobjeto em um projeto que tem uma referência aoobjetode biblioteca 2.8 de objetos de dados do Microsoft ActiveX COM:

Dim cmd As New ADODB.Command

No entanto, se você estiver usando aclasse do COMcomo base para uma classede derivada, você deve usar a classe interoperabilidade que representa a COMclasse, como no código a seguir:

Class DerivedCommand
    Inherits ADODB.CommandClass
End Class
ObservaçãoObservação

Assemblies de interoperabilidade implicitamente implementam interfaces que representam as classes COM . Você não deve tentar usar o resultarãoImplementsdemonstrativo para implementar essas interfaces ou um erro .

Tipos de dados para parâmetros e valores de retorno

Ao contrário dos membros dos assemblies padrão, membros do assembly de interoperabilidade podem ter tipos de dados que diferem daqueles usados nadeclaraçãode original do objeto. Embora assemblies de interoperabilidade implicitamente converter COM tipos para tipos compatíveis Common Language Runtime , você deve prestar atenção aos tipos de dados que são usados por ambos os lados para evitar erros de tempo de execução . Por exemplo, em objetos COM criados no Visual Basic 6.0 e versões anteriores, os valores do tipo Integer pressupõem o .NET Framework tipo equivalente, Short. É recomendável que você use o Pesquisador de Objetos para examinar as características dos membros importados, antes de usá-los.

Métodos COM nível de módulo

COM são usados, criando uma instância de umaclasse de COMusando o Newpalavra-chave e, em seguida, chamar métodos do objeto. Uma exceção a essa regra envolve COM AppObj ou GlobalMultiUse COM classes. Tais classes semelhantes aos métodos de nível de módulo em Visual Basic 2005 classes. Visual Basic 6.0 e versões anteriores implicitamente criar instâncias como objetos para você na primeira vez que você chamar um dos seus métodos. Por exemplo, no Visual Basic 6.0 você pode adicionar uma referência para a Microsoft DAO 3.6 Object Library e a chamada a DBEngine método sem primeiro criar uma instância:

Dim db As DAO.Database
' Open the database.
Set db = DBEngine.OpenDatabase("C:\nwind.mdb")
' Use the database object.

Visual Basic 2005requer que você sempre criar instâncias COM objetos que você possa usar seus métodos. Para usar esses métodos em Visual Basic 2005, declare uma variável da classe desejado e use a palavra-chave new para atribuir o objeto àvariávelde objeto. O Shared palavra-chave pode ser usada quando você deseja garantir que apenas uma instância da classe é criada.

' Class level variable.
Shared DBEngine As New DAO.DBEngine

Sub DAOOpenRecordset()
    Dim db As DAO.Database
    Dim rst As DAO.Recordset
    Dim fld As DAO.Field
    ' Open the database.
    db = DBEngine.OpenDatabase("C:\nwind.mdb")

    ' Open the Recordset.
    rst = db.OpenRecordset(
        "SELECT * FROM Customers WHERE Region = 'WA'",
        DAO.RecordsetTypeEnum.dbOpenForwardOnly,
        DAO.RecordsetOptionEnum.dbReadOnly)
    ' Print the values for the fields in the debug window.
    For Each fld In rst.Fields
        Debug.WriteLine(fld.Value.ToString & ";")
    Next
    Debug.WriteLine("")
    ' Close the Recordset.
    rst.Close()
End Sub

Sem tratamento de Erros nos manipuladores de eventos

Um problema comum de interoperabilidade envolve erros nos manipuladores de evento para manipulam eventos gerados pelos objetos COM . Esses erros são ignorados, a menos que especificamente procurar erros usando On Error ou Try...Catch...Finally instruções. Por exemplo, o exemplo a seguir é de um deVisual Basic 2005projeto tem uma referência aoobjetode biblioteca 2.8 de objetos de dados do Microsoft ActiveX COM.

' To use this example, add a reference to the 
'     Microsoft ActiveX Data Objects 2.8 Library  
' from the COM tab of the project references page.
Dim WithEvents cn As New ADODB.Connection
Sub ADODBConnect()
    cn.ConnectionString =
    "Provider=Microsoft.Jet.OLEDB.4.0;" &
    "Data Source=C:\NWIND.MDB"
    cn.Open()
    MsgBox(cn.ConnectionString)
End Sub

Private Sub Form1_Load(ByVal sender As System.Object,
    ByVal e As System.EventArgs) Handles MyBase.Load

    ADODBConnect()
End Sub

Private Sub cn_ConnectComplete(
    ByVal pError As ADODB.Error,
    ByRef adStatus As ADODB.EventStatusEnum,
    ByVal pConnection As ADODB.Connection) Handles cn.ConnectComplete

    '  This is the event handler for the cn_ConnectComplete event raised 
    '  by the ADODB.Connection object when a database is opened.
    Dim x As Integer = 6
    Dim y As Integer = 0
    Try
        x = CInt(x / y) ' Attempt to divide by zero.
        ' This procedure would fail silently without exception handling.
    Catch ex As Exception
        MsgBox("There was an error: " & ex.Message)
    End Try
End Sub

Este exemplo gera um erro , conforme o esperado. No entanto, se você tentar fazer o mesmo exemplo, sem a Try...Catch...Finally bloco, o erro será ignorado como se você usou o OnError Resume Next demonstrativo. Sem o tratamento de erro , a divisão por zero falhará silenciosamente. Porque tais erros nunca elevar uma exceção não tratada erros, é importante que você usar alguma formulário de manipulação de exceção nos manipuladores de evento para manipulam eventos de objetos COM .

Noções básicas sobre erros de interoperabilidade COM

Sem erro chamadas interop manuseio freqüentemente geram erros que fornecem poucas informações. Sempre que possível, use o tratamento estruturado de erro para fornecer mais informações sobre problemas quando eles ocorrerem. Isso pode ser especialmente útil quando você depurar aplicativos. For example:

Try
    ' Place call to COM object here.
Catch ex As Exception
    ' Display information about the failed call.
End Try

Você pode encontrar informações como, por exemplo, a descrição do erro HRESULT e a fonte de erros COM examinando o conteúdo doobjetode exceção.

Problemas de controle de ActiveX

A maioria dos controles de ActiveX que funcionam com Visual Basic 6.0 trabalhar com Visual Basic 2005 sem problemas. As principais exceções são os controles do contêiner ou controles que visualmente contêm outros controles. Alguns exemplos de controles mais antigos que não funcionam corretamente com Visual Studio são da seguinte maneira:

  • Controle Frame do Microsoft Forms 2.0

  • O controle de-para baixo, também conhecido como o controle de rotação

  • Controle de guia de Sheridan

Há apenas algumas soluções para problemas de controle ActiveX sem suporte. Você pode migrar os controles existentes para Visual Studio se você possui o código fonte original. Caso contrário, você pode verificar com fornecedores de software para atualizadas.Versões compatíveis do NET-de controles para substituir sem suporte a controles de ActiveX.

Passagem ReadOnly Propriedades de controles ByRef

Visual Basic 2005às vezes gera erros de COM , como, por exemplo, "CTL_E_SETNOTSUPPORTED de 0x800A017F de erro" Quando você passar ReadOnly Propriedades de alguns controles mais antigos de ActiveX como ByRef parâmetros para outros procedimentos. Chamadas de procedimento de semelhante do Visual Basic 6.0 não aumente um erroe os parâmetros são tratados como se você os passados por valor. A mensagem de erro que você vê na Visual Basic 2005 é oobjeto do COMrelatórios que você está tentando alterar uma propriedade que não tem uma propriedadede Setprocedimento.

Se você tiver acesso ao procedimento que está sendo chamado, você pode impedir que esse erro usando o ByValapalavra-chave para declarar parâmetros que aceitam ReadOnly Propriedades. For example:

Sub ProcessParams(ByVal c As Object)
    'Use the arguments here.
End Sub

Se você não tem acesso ao código fonte para o procedimento que está sendo chamado, você pode forçar a propriedade a serem passados por valor, adicionando um conjunto extra de colchetes em torno da chamada de procedimento. Por exemplo, em um projeto que tem uma referência aoobjetode biblioteca 2.8 de objetos de dados do Microsoft ActiveX COM, você pode usar:

Sub PassByVal(ByVal pError As ADODB.Error)
    ' The extra set of parentheses around the arguments
    ' forces them to be passed by value.
    ProcessParams((pError.Description))
End Sub

Implantar Assemblies que expõem a interoperabilidade

Implantar assemblies expõem interfaces COM apresenta alguns desafios únicos. Por exemplo, um possível problema ocorre quando o mesmo COM assemblyde referência de aplicativos separados. Essa situação é comum quando uma nova versão de um assembly é instalado e o outro aplicativo ainda está usando a versão antiga do assembly. Se você desinstalar um assembly que compartilha uma DLL, você pode, inadvertidamente, tornará indisponível para outros assemblies.

Para evitar esse problema, você deve instalar compartilhado assemblies para o Cache Global de assemblies (GAC) e usa um MergeModule para o componente. Se você não pode instalar o aplicativo no GAC, ele deverá ser instalado para CommonFilesFolder em uma versão-subdiretório específico.

Os assemblies não são compartilhados devem estar localizados no diretório com o aplicativode chamada lado a lado.

Consulte também

Tarefas

Passo a passo: Implementando a herança com objetos COM (Visual Basic)

How to: Adicionar Mesclar módulos para um projeto de implantação

Referência

MarshalAsAttribute

Tlbimp. exe (importador da biblioteca)

Tlbexp. exe (exportador da biblioteca)

Declaração Inherits

Conceitos

Cache global de assemblies

Outros recursos

Interoperabilidade COM (Visual Basic)