none
VB6 usando com+ feito em vb.net RRS feed

  • Pergunta

  •  

    Tenho que criar uma dll em vb.net que será utilizada em vb6. Como nunca trabalhei com esse tipo de interação procurei materias na net sobre isso e achei uma página que explica passo a passo como fazer (http://www.bufaloinfo.com.br/Artigos/Artigo220702.asp).

    Executei todos os passos, mas na hora de executar o comando RegSvcS para registrar a dll ele retorna o seguinte erro:

    1: Falha ao carregar o conjunto de módulos <assembly> 'c:/teste/mc.dll'.

    2: O formato do arquivo  'c:/teste/mc.dll' é inválido.

     

    Não consegui descobrir o porque do erro. Estou travado por causa deste problema e tenho prazo até segunda para entregar o projeto. Agradeço qualquer ajuda que possam me fornecer.

    quinta-feira, 29 de novembro de 2007 17:59

Respostas

  • Do lado do VB.NET:

     

    Imports System.EnterpriseServices
    Imports System.EnterpriseServices.ObjectPoolingAttribute
    Imports System.Runtime.InteropServices
     
    <InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)> _
    Public Interface Imyinterface
        Function Calcular(ByVal v As Integer) As Integer
    End Interface
     
    <JustInTimeActivation(), _
    ObjectPooling(MinPoolSize:=5, MaxPoolSize:=5, Enabled:=True)> _
    <Runtime.InteropServices.ClassInterface(Runtime.InteropServices.ClassInterfaceType.None)> _
    Public Class MinhaClasse
        Implements Imyinterface
     
        Public Function Calcular(ByVal v As Integer) As Integer Implements Imyinterface.Calcular
            Calcular = v * 2
        End Function
    End Class

     

    Marquei a opção de interoperabilidade COM e nas propriedades do projeto o namespace "MeuNamespace". (também verifique no arquivo "AssemblyInfo.vb" -- no Solution Explorer pressione "Show All Files" para vê-lo -- se o atributo ComVisible está seta como true).

     

    Uso no VB6 com late binding:

     

    Dim ret As Integer
    Dim o As Object
     
    Set o = CreateObject("MeuNamespace.MinhaClasse")
     
    ret = o.Calcular(2)

    MsgBox ret

     

     

    Uso no VB6 com early binding:

     

    Dim ret As Integer
    Dim o As New SuaDLL.MinhaClasse

     

    ret = o.Calcular(2)

    MsgBox ret

     

    Quando a DLL é compilada no VB.NET ela já é registrada automaticamente no diretório em que está. Para registrar e desregistrar manualmente use o programa RegAsm.exe.

     

    Desregistrar:

     

    regasm /unregister SuaDLL.dll

     

    Registar com gerando a Type Library (para poder fazer early binding):

     

    regasm /tlb SuaDLL.dll

     

     

     

     

     

    segunda-feira, 3 de dezembro de 2007 15:07

Todas as Respostas

  • Nas propriedades do projeto, aba "Compile" marque a opção "Register for COM interop".

     

    Também é conveniente que se crie interfaces pelos motivos e do modo discutidos aqui:

    http://forums.microsoft.com/msdn-br/ShowPost.aspx?PostID=1242792&SiteID=21

     

    quinta-feira, 29 de novembro de 2007 18:33
  • MacGyver, meu projeto já estava com a opção "Register for COM interop" habilitada. Dei uma olhada no link q vc enviou e outros que lá estão. Mesmo assim o problema persiste. Por curiositade ("Desespero") habilitei a opção "Delay sign only" na aba "Signing", quando compilei o projeto o VS acusou o seguinte erro:

     

    Error 1 Cannot register assembly "C:\teste\mc.dll". Could not load file or assembly 'mc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a2ca7d5ada4cc639' or one of its dependencies. Strong name validation failed. (Exception from HRESULT: 0x8013141A) mc

     

    Estou incluindo abaixo o codigo que estou utilizando. Talvez vc consiga achar o erro mais facilmente.
    Obrigado.

     

    Imports System.EnterpriseServices

    Imports System.EnterpriseServices.ObjectPoolingAttribute

    Imports System.Runtime.InteropServices

    <InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)> _

    Public Interface Imyinterface

    Function Calcular(ByVal v As Int32) As Int32

    End Interface

    <ProgIdAttribute("MinhaClasse"), _

    JustInTimeActivation(), _

    ObjectPooling(MinPoolSize:=5, MaxPoolSize:=5, Enabled:=True)> _

    <Runtime.InteropServices.ClassInterface(Runtime.InteropServices.ClassInterfaceType.None)> _

    Public Class MinhaClasse

    Inherits ServicedComponent

    Implements Imyinterface

    Public Function Calcular(ByVal v As Integer) As Integer Implements mc.Imyinterface.Calcular

    Calcular = v * 2

    End Function

    End Class

    sexta-feira, 30 de novembro de 2007 10:49
  • Não sei se aquela classe que você está herdando pode interferir, imagino que não.

     

    De qualquer forma, fiz um teste aqui com a classe abaixo, apenas tirando referência à classe que vc está herdando:

     

    Imports System.EnterpriseServices
    Imports System.EnterpriseServices.ObjectPoolingAttribute
    Imports System.Runtime.InteropServices
     
    <InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)> _
    Public Interface Imyinterface
        Function Calcular(ByVal v As Integer) As Integer
    End Interface
     
    <ProgIdAttribute("MinhaClasse"), _
    JustInTimeActivation(), _
    ObjectPooling(MinPoolSize:=5, MaxPoolSize:=5, Enabled:=True)> _
    <Runtime.InteropServices.ClassInterface(Runtime.InteropServices.ClassInterfaceType.None)> _
    Public Class MinhaClasse
        Implements Imyinterface
     
        Public Function Calcular(ByVal v As Integer) As Integer Implements Imyinterface.Calcular
            Calcular = v * 2
        End Function
    End Class

     

     

    Testei usando a interface:

     

    Dim t As Type
    Dim o As Imyinterface
     
    Try
        t = Type.GetTypeFromProgID("MinhaClasse", True)
        o = CType(Activator.CreateInstance(t), Imyinterface)
     
    Catch ex As TypeLoadException
        MessageBox.Show(ex.Message)
        Return
    End Try
     
    Dim ret As Integer = o.Calcular(2)
     
    MessageBox.Show(ret.ToString())

     

     

     

    Late binding sem a interface:

     

    Dim t As Type
    Dim o As Object
     
    Try
        t = Type.GetTypeFromProgID("MinhaClasse", True)
        o = Activator.CreateInstance(t)
     
    Catch ex As TypeLoadException
        MessageBox.Show(ex.Message)
        Return
    End Try
     
    Dim param As Object() = New Object() {2}
    Dim ret As Integer
     
    ret = Convert.ToInt32(t.InvokeMember("Calcular", Reflection.BindingFlags.InvokeMethod, Nothing, o, param))
     
    MessageBox.Show(ret.ToString())

     

     

     

     

    Late Binding estilo VB6:

     

    Dim o As Object
     
    Try
        o = CreateObject("MinhaClasse")
    Catch ex As TypeLoadException
        MessageBox.Show(ex.Message)
        Return
    End Try
     
    Dim ret As Integer = Convert.ToInt32(o.Calcular(2))
     
    MessageBox.Show(ret.ToString())

     

     

    Funcionou de todos os jeitos. Pessoalmente, ao invés de usar o atributo "ProgIdAttribute", eu definiria um namespace para o projeto  (ou pata as classes individualmente) para que fique mais de acordo com o padrão. Por exemplo, você poderia definir um namespace "MeuNamespace" para a DLL com a classe "MinhaClasse" e então a invocaria os métodos dessa classe assim (na invocação com a interface):

     

    Dim t As Type
    Dim o As Imyinterface
     
    Try
        t = Type.GetTypeFromProgID("MeuNamespace.MinhaClasse", True)
        o = CType(Activator.CreateInstance(t), Imyinterface)
     
    Catch ex As TypeLoadException
        MessageBox.Show(ex.Message)
        Return
    End Try
     
    Dim ret As Integer = o.Calcular(2)
     
    MessageBox.Show(ret.ToString())

     

     

     

     

     

     

     

     

     

     

     

    sábado, 1 de dezembro de 2007 19:36
  • O problema continua. Criei um novo projeto com o código que você forneceu. Compila sem problemas, mas na hora de usar o REGSVCS ele apresenta a mesma mensagem de erro que indiquei anteriormente. Provavelmente estou configurando algo errado. Você poderia me passar as configurações que você utilizou?

     

    Obrigado.

    segunda-feira, 3 de dezembro de 2007 11:26
  • Do lado do VB.NET:

     

    Imports System.EnterpriseServices
    Imports System.EnterpriseServices.ObjectPoolingAttribute
    Imports System.Runtime.InteropServices
     
    <InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)> _
    Public Interface Imyinterface
        Function Calcular(ByVal v As Integer) As Integer
    End Interface
     
    <JustInTimeActivation(), _
    ObjectPooling(MinPoolSize:=5, MaxPoolSize:=5, Enabled:=True)> _
    <Runtime.InteropServices.ClassInterface(Runtime.InteropServices.ClassInterfaceType.None)> _
    Public Class MinhaClasse
        Implements Imyinterface
     
        Public Function Calcular(ByVal v As Integer) As Integer Implements Imyinterface.Calcular
            Calcular = v * 2
        End Function
    End Class

     

    Marquei a opção de interoperabilidade COM e nas propriedades do projeto o namespace "MeuNamespace". (também verifique no arquivo "AssemblyInfo.vb" -- no Solution Explorer pressione "Show All Files" para vê-lo -- se o atributo ComVisible está seta como true).

     

    Uso no VB6 com late binding:

     

    Dim ret As Integer
    Dim o As Object
     
    Set o = CreateObject("MeuNamespace.MinhaClasse")
     
    ret = o.Calcular(2)

    MsgBox ret

     

     

    Uso no VB6 com early binding:

     

    Dim ret As Integer
    Dim o As New SuaDLL.MinhaClasse

     

    ret = o.Calcular(2)

    MsgBox ret

     

    Quando a DLL é compilada no VB.NET ela já é registrada automaticamente no diretório em que está. Para registrar e desregistrar manualmente use o programa RegAsm.exe.

     

    Desregistrar:

     

    regasm /unregister SuaDLL.dll

     

    Registar com gerando a Type Library (para poder fazer early binding):

     

    regasm /tlb SuaDLL.dll

     

     

     

     

     

    segunda-feira, 3 de dezembro de 2007 15:07
  • Agora consegui, muito obrigado.

    quinta-feira, 6 de dezembro de 2007 10:07
  • Angus MacGyver

     

     

    Muito obrigado foi de grande auxilio para mim tb

     

     

     

    Eduardo Priore

    quinta-feira, 29 de maio de 2008 12:28
  • Foltran,

     

    Estou com o mesmo erro, onde vc estava errando ?

     

    Obrigado

    sexta-feira, 4 de julho de 2008 16:29