Compartilhar via


Solucionando problemas de interoperabilidade (Visual Basic)

Quando você interoperar entre o 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 fazem 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 gerenciados são expostos com. Por exemplo, estruturas de bibliotecas de classes devem especificar o BStr não gerenciados tipo 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 os tipos gerenciados a serem expostos como tipos não gerenciados.

A exportação de seqüências de comprimento fixo para código não gerenciado

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 outras linguagens, Visual Basic 2005 inclui um caractere de finalização durante a exportação de seqüências de caracteres. A melhor maneira de resolver essa incompatibilidade é exportar a seqüências de caracteres que não possuem o caractere de finalização como matrizes de Byte ou Char.

Exportação de hierarquias de herança

Gerenciado classe hierarquias nivelar out quando expostos como objetos COM. Por exemplo, se você define uma classe base com um membro e, em seguida, herda da classe base em uma classe derivada que é exposta como um objeto COM, os clientes que usam a classe derivada do objeto COM não poderão usar os membros herdados. Membros de classe base podem ser acessados dos objetos COM somente como instâncias de uma classe base e somente se a classe base também é criada como um objeto 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 um objeto 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 um objeto COM, os novos nomes de método gerado poderiam ser Synch e Synch_2.

A renomeação, dois problemas pode causar os consumidores do objeto COM.

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

  2. Os nomes de método gerado na classe exposto como um objeto COM podem 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 quase como se eles fossem substituições de código gerenciado para os objetos COM que eles representam. No entanto, porque eles são invólucros e não os objetos de 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 assemblies padrão, classes COM são expostas em assemblies de interoperabilidade como uma interface e uma classe que representa a classe COM. Nome da interface é idêntico da classe COM. O nome da classe interoperabilidade é o mesmo da classe COM original, mas com a palavra "Class" acrescentado. Por exemplo, suponha que você tenha um projeto com uma referência a um assembly de interoperabilidade para um objeto COM. Se o nome da classe COM MyComClass, IntelliSense e o Pesquisador de objetos mostram uma interface denominada MyComClass e uma classe chamada MyComClassClass.

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

Em geral, você pode criar uma instância de um .NET Framework de classe usando o New instrução com um nome de classe. Ter uma classe COM representado por um assembly de interoperabilidade é o único caso em que você pode usar o New instrução com uma interface. A menos que você estiver usando a classe COM um Inherits instrução, você pode usar a interface como faria com uma classe. O código a seguir demonstra como criar um Command o objeto em um projeto que tem uma referência ao objeto objetos de dados do Microsoft ActiveX 2.8 biblioteca COM:

Dim cmd As New ADODB.Command

No entanto, se você estiver usando a classe COM como base para uma classe derivada, você deve usar a classe de interoperabilidade que representa a classe COM, como no código a seguir:

Class DerivedCommand
    Inherits ADODB.CommandClass
End Class

Dica

Assemblies de interoperabilidade implicitamente implementam interfaces que representam as classes COM.Você não deve tentar usar o Implements fará com que a instrução 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 na declaração do objeto original. Embora os assemblies de interoperabilidade implicitamente convertem tipos COM compatível tipos do 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 de nível COM módulo

A maioria dos objetos COM são usados, criando uma instância de uma classe de COM usando o New palavra-chave e, em seguida, chamar métodos do objeto. Uma exceção a essa regra envolve os objetos COM que contêm AppObj ou GlobalMultiUse classes COM. Essas 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 criam instâncias desses 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 sempre criar instâncias de objetos COM que você possa usar seus métodos. Para usar esses métodos em Visual Basic 2005, declare uma variável da classe desejada e use a nova palavra-chave para atribuir o objeto para a variável de 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

Erros não tratados nos manipuladores de eventos

Um problema comum de interoperabilidade envolve erros de manipuladores de eventos 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 Visual Basic 2005 projeto tem uma referência ao objeto objetos de dados do Microsoft ActiveX 2.8 biblioteca 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 instrução. Sem o tratamento de erros, a divisão por zero falhará silenciosamente. Porque tais erros nunca geram erros de exceção não tratada, é importante que você usa alguma forma de tratamento de exceção no manipuladores de eventos que tratam os eventos dos 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 structured tratamento de erros para fornecer mais informações sobre problemas quando eles ocorrerem. Isso pode ser especialmente útil ao depurar aplicativos. Por exemplo:

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 origem de erros COM examinando o conteúdo do objeto de 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 controles do recipiente, ou controles que visualmente contêm outros controles. Alguns exemplos de controles mais antigos que não funcionam corretamente com o Visual Studio são os seguintes:

  • Controle Frame do Microsoft Forms 2.0

  • Controle acima-abaixo, também conhecido como o controle de rotação

  • Controle de guia de Sheridan

Há apenas algumas soluções alternativas para problemas de controle de 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 for atualizado.Compatível com versões dos 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 "CTL_E_SETNOTSUPPORTED de 0x800A017F de erro", ao passar ReadOnly propriedades de alguns controles mais antigos de ActiveX como ByRef parâmetros para outros procedimentos. Chamadas de procedimento semelhante a partir de Visual Basic 6.0 gera um erro e os parâmetros são tratados como se você os passados por valor. A mensagem de erro que você vê na Visual Basic 2005 é o objeto COM emissão de relatórios que você está tentando alterar uma propriedade que não tem uma propriedade Set procedimento.

Se você tiver acesso ao procedimento que está sendo chamado, você pode evitar esse erro, usando o ByVal palavra-chave para declarar parâmetros que aceitam ReadOnly propriedades. Por exemplo:

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 do procedimento de chamada. Por exemplo, em um projeto que tem uma referência ao objeto objetos de dados do Microsoft ActiveX 2.8 biblioteca 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 que expõem interfaces COM apresenta alguns desafios específicos. Por exemplo, um possível problema ocorre ao mesmo assembly COM referência a aplicativos separados. Essa situação é comum quando uma nova versão de um assembly é instalada 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 os outros assemblies.

Para evitar esse problema, você deve instalar assemblies compartilhados no Global Assembly Cache (GAC) e usar um MergeModule para o componente. Se você não pode instalar o aplicativo no GAC, ele deve ser instalado para CommonFilesFolder em um subdiretório específico da versão.

Módulos (assemblies) que não é compartilhadas deve estar localizado no diretório com o aplicativo de chamada lado a lado.

Consulte também

Tarefas

Instruções passo a passo: implementando a herança com objetos COM (Visual Basic)

Referência

MarshalAsAttribute

Tlbimp.exe (Importador de Biblioteca de Tipos)

Tlbexp.exe (Exportador de Biblioteca de Tipos)

Instrução Inherits

Conceitos

Cache de assemblies global

Outros recursos

Interoperabilidade COM (Visual Basic)