3

私は、データ ソースからデータを読み取り、他のアプリがその関数を呼び出してそれらのデータを取得できるようにするラッパーとして機能する c# で記述された .net dll を持っています。問題は、.net dll が .net アプリ以外に使用されるとは予想していなかったため、これはすべて vba/powerpoint マクロで使用されると言われましたが、これは vb6 アプリにかなり似ていると考えています。 、それが私が今それをテストすることを計画している方法です。

グーグルで検索したり、ここに質問を投稿したりした後、vb6内でdllを参照することができましたが、パラメーターを持つ関数を呼び出そうとすると、エラーのランタイムメッセージが表示されます450 引数の数が間違っているか、プロパティの割り当てが無効です。

質問

それで、私は何を間違っていますか?また、vb6/vba アプリから呼び出すことができるパラメーターを持つ関数を持つ .net dll を適切に記述する方法について学ぶことができるリソースまたはサンプル コードを提供してもらえますか?

そして、私のコードが少し乱雑すぎて読むことができない場合:)、おそらく、私が codeproject から学んだこのサンプルでパラメーターを機能させる方法を教えてください。そこにいくつかのパラメーターを含めると、同じエラーメッセージが返されます.

更新:

ここで別のサンプルコードのセットを見つけましたが、残念ながらパラメーターを整数として渡すだけで、パラメーターを文字列として渡すサンプル関数を実行しようとすると、同じエラーが発生します。ここで何か基本的なことが欠けていますか? 初心者を炎上させたい人はいますか?

アップデート 2:

この問題に出くわした他の誰かがいる場合に備えて、なぜ、または何が問題を引き起こしているのかを実際には知りませんでしたが、プロジェクトはまだかなり小さいので、文字列を返すことができた dll の作業サンプルを使用するだけです適切に機能ごとに機能を移動し始めると、現在は正常に機能しています:)

ありがとう!!!

.net dll コードは次のとおりです。

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)
        {
        ...
        }
}

そして、これは私が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
4

4 に答える 4

2

あなたが行方不明になっていることに気付きました[ComVisible(true)]

インターフェイス ヘッダーは次のようになります。

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

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

クラス ヘッダーは次のようになります。

[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;
    }
}
于 2009-08-19T00:41:37.267 に答える
1

このコードのチャンクを変更してみてください:-

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]

[InterfaceType(ComInterfaceType.InterfaceIsDual)]

エラーが発生する理由はわかりませんが、初期 (または VTable) バインディングは、VB6 コードが試みているように見えますが、InterfaceIsIDispatchそれをサポートしていません。VB6 自体が遅延バインディングにフォールバックしている可能性がありますが、なぜそうしたいのでしょうか?

また、既存の COM インターフェイスをエミュレートする必要がある場合にのみ必要なすべての DispId 属性を削除します。

于 2009-08-17T12:42:30.787 に答える
1

DispID(1) は ToString などのために予約されていると思います (久しぶりです) DispID を 2 から開始してみてください。

于 2009-08-17T12:44:02.190 に答える