Pergunta

Eu tenho um .net dll escrito em c # que lê dados de um fonte de dados e atua como um wrapper para permitir que outros aplicativos para chamar sua função para recuperar esses dados. a coisa é que eu não antecipar o .net dll para ser usado para outros fins que .net apps, então agora foi-me dito tudo isso vai ser usado em uma macro VBA / powerpoint que figura i é bastante semelhante a um aplicativo VB6 , de modo que é como eu estou planejando para testá-lo agora.

depois de algum googling e até mesmo a postar alguma pergunta aqui em Então, eu conseguir ter a dll a ser referenciado dentro de VB6, mas quando eu tentar chamar uma função que tem quaisquer parâmetros, vou pegar o erro run-time mensagem de erro 450 número errado de argumentos ou atribuição de propriedade inválido.

Perguntas

Então, o que estou fazendo de errado? e alguém por favor pode fornecer alguns recursos ou códigos de amostra que eu posso aprender sobre como escrever corretamente um .net dll que tem funções com parâmetros que podem ser chamados de VB6 / VBA aplicativo?

E se meus códigos são um pouco demasiado confuso para ler :), então talvez vocês podem ajudar a me dizer como colocar parâmetros para o trabalho em este exemplo que eu aprender com codeproject , seu retorno a mesma mensagem de erro quando eu incluir alguns parâmetros lá.

ATUALIZAÇÕES:

eu encontrei um outro conjunto de códigos de amostra aqui , mas infelizmente ele só passa parâmetros como número inteiro, e quando eu tento fazer uma função de exemplo que passa parâmetros como corda, eu recebo o mesmo erro. Estou faltando alguma coisa fundamentos aqui? cuidado ninguém chama uma noobie?

Atualizações 2:

Apenas no caso de haver qualquer outra pessoa que tropeçou em este problema, eu realmente não descobri por que ou o que estava causando o problema, mas desde que o projeto ainda era bastante pequeno, eu só uso uma amostra trabalhando para a dll que foi capaz a seqüência de retorno adequada e iniciar a função por função movendo-se para ele, e ele está funcionando bem agora:)

thanks !!!

os códigos .net dll são os seguintes:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Data.OleDb;
using System.Data;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
//using System.Windows.Forms;

namespace DtasApiTool
{

    [Guid("D6F88E95-8A27-4ae6-B6DE-0542A0FC7040")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface _Program
    {
        [DispId(1)]
        string Get_All_Locales(string test);

        [DispId(2)]
        string Get_All_Levels(string locale);

        [DispId(3)]
        string Get_Subjects_ByLocaleLevelId(string locale, int levelId);

        [DispId(4)]
        string Get_Topic_ByLevelIdLocaleSubjectId(int levelId, string locale, int subjectId);

        [DispId(5)]
        string Get_Subtopic_ByLevelIdLocaleSubjectIdTopicId(int levelId, string locale, int subjectId, int topicId);

        [DispId(6)]
        string Get_Skill_ByLevelIdLocaleSubjectIdTopicIdSubtopicId(int levelId, string locale, int subjectId, int topicId, int subtopicId);

        [DispId(7)]
        string Get_All_Subjects(string locale);

        [DispId(8)]
        void Constructor(string directory);

    }

    [Guid("13FE32AD-4BF8-495f-AB4D-6C61BD463EA5")]
    [ClassInterface(ClassInterfaceType.None)]
    [ProgId("DtasApiTool.Program")]
    public class Program : _Program
    {
        private string connStr = "";
        private string xmlLocation = "";

        public Program(){

        }

        public void Constructor(string directory)
        {
          ...  
        }


        #region This part contains all the internal functions

        /// <summary>
        /// return the component lesson given a locale and skill id
        /// </summary>
        /// <param name="locale"></param>
        /// <param name="skillId"></param>
        /// <returns></returns>
        internal string Get_Component_Lesson(string locale, string skillId)
        {
            ...
        }

        /// <summary>
        /// return a xmlFile containing all the information from the Skill Analysis
        /// </summary>
        /// <param name="fileLocation">raw xml file location, i.e. C://datapath/raw_dato.xml</param>
        /// <returns> the location of the output xml file.</returns>
        internal string Process_Skill_Analysis_Report(string fileLocation)
        {            
...
}

        #endregion

        /// <summary>
        /// Returns all the locale which is in the database currently.
        /// </summary>
        /// <returns></returns>
        public string Get_All_Locales(string test)
        {
        ...
        }
}

e isto é como eu estou chamando-o de VB6:

Option Explicit

Private Sub Form_Load()        
    Dim obj As DtasApiTool.Program
    Set obj = New DtasApiTool.Program

    Dim directory As String
    directory = """" + "C:\Documents and Settings\melaos\My Documents\Visual Studio 2008\Projects\app\bin\Release\" + """"

    'obj.Constructor directory
    Dim func As String
   func = obj.Get_All_Locales(directory)

End Sub
Foi útil?

Solução

Eu percebi que você está perdendo [ComVisible(true)].

Interface cabeçalho deve ser semelhante a:

[Guid("CF4CDE18-8EBD-4e6a-94B4-6D5BC0D7F5DE")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
[ComVisible(true)]
public interface IFoo {

    [DispId(1)]
    string MyMethod(string value);
}

Class cabeçalho deve ser semelhante a:

[Guid("7EBD9126-334C-4893-B832-706E7F92B525")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
[ProgId("MyNamespace.Foo")]
public class Foo: IFoo {

    public string MyMethod(string value){
        return somestring;
    }
}

Outras dicas

Tente alterar este pedaço de código: -

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]

para

[InterfaceType(ComInterfaceType.InterfaceIsDual)]

Eu não sei por que você obter o erro você é no entanto mais cedo (ou VTable) de ligação é o que você VB6 código parece estar tentando, mas InterfaceIsIDispatch não suporta isso. Sua possível VB6 em si está caindo de volta para a ligação tardia mas por que você quer que ele?

Também soltar todos os atributos DispId eles só são necessárias se você realmente precisa para emular uma interface COM existente.

Eu acredito DispID (1) é reservado para ToString ou algo assim (ele tem sido um tempo) Tente iniciar suas DispIDs a 2.

Você tentou olhando para a biblioteca de tipos (usando Oleview.exe) depois de exportadas / registrou a montagem?

Minha suspeita é que todos os seus métodos retornam cordas, enquanto que os métodos COM tendem a retornar de HRESULT (nenhuma idéia se isso geralmente é verdade - na verdade sua página exemplo codeproject parece sugerir o contrário), o que significa que você precisa colocar o seu de entrada e saída para os argumentos de método e explicitamente organizar-los com [in], [out] e / ou [retval].

De qualquer forma, dê uma olhada na biblioteca tipo e verificar se ele se parece com você espera que ele olhar. Se não você pode ter que organizar explicitamente seus tipos usando o atributo MarshalAs.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top