简体   繁体   English

如何在 Microsoft Access 中使用 C# DLL

[英]How to use a C# DLL in Microsoft Access

I have created the class below in Visual Studio 2019 with "Make Assembly COM-Visible" set to true and "Register for COM interop" checked.我在 Visual Studio 2019 中创建了下面的 class,其中“使程序集 COM-Visible”设置为 true,并选中“注册 COM 互操作”。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace SimpleCalc
{

    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    [Guid("95F54E1A-826C-4766-9FE9-D32C47B07504")]
    public interface _Test
    {
        string HelloWorld { get; }
    }

    [ClassInterface(ClassInterfaceType.None)]
    [Guid("9F7248AF-4E59-4938-AECC-B938703F33BB")]
    [ProgId("SimpleCalc.Test")]
    public class Test : _Test
    {
        public string HelloWorld { get { return "Hello, World! "; } }
    }
}

Code compiles fine and I can reference it in VBA and the property "Hello World" is shown in the class "Test" in the object browser.代码编译良好,我可以在 VBA 中引用它,属性“Hello World”显示在 object 浏览器的 class“测试”中。

However when I try to access in an onClick event subroutine with the code但是,当我尝试使用代码访问 onClick 事件子例程时

Dim o As Test
Set o = New Test 
MsgBox o.HelloWorld

error:'429' "ActiveX component can't create object" is generated at Set o = New Test.错误:'429'“ActiveX 组件无法创建对象”在 Set o = New Test 处生成。

What am I doing wrong?我究竟做错了什么?

Well, first of all?嗯,首先? You not marked the interface as public您没有将接口标记为公开

eg;例如;

    public interface _Test

Next up, I would remove the Prog_id - you don't need it, and I think that also messing this up.接下来,我将删除 Prog_id - 你不需要它,我认为这也会搞砸。

And, really, I don't see any case to be made for building a infterface here?而且,真的,我看不出有什么理由在这里建立一个接口? I doubt in c# (or for sure in VBA), you not going to need to declarer public member variable types derived from that class without having to create a instance of that class (it you need to do that - then ok - I suppose one can make the case for a interface, but OTHER then this reason? No need).我怀疑在 c# (或者肯定在 VBA 中),你不需要声明从 class 派生的公共成员变量类型,而不必创建 class 的实例,然后我想你需要可以做一个接口的案例,但是其他的那么这个原因吗?不需要)。

One does not really need to bother with the GUIDS in the code either.也不需要担心代码中的 GUIDS。 The project settings will take care of that.项目设置将解决这个问题。

And you don't really need a namespace - again project default takes care of that.而且您实际上并不需要命名空间 - 项目默认会再次处理这个问题。

So, now we down to this:所以,现在我们归结为:

using System.Runtime.InteropServices;

[ClassInterface(ClassInterfaceType.AutoDual)]
public class COMTest1
    {
        public string HelloWorld
        {
            get
            {
                return "Hello, World! ";
            }
        }

    }

Ok, now that is much better, Of course: we need to check the "com visible" box here:好的,现在好多了,当然:我们需要在这里选中“com visible”框:

在此处输入图像描述

or you can just above the the class interface type setting add a COMvisible=true.或者您可以在 class 接口类型设置上方添加一个 COMvisible=true。

And during development, you can (should) have the COM assembly registered.在开发过程中,您可以(应该)注册 COM 程序集。 On target machines you have to do a regasm.exe, but on your dev box, you can get VS to do this for you.在目标机器上,您必须执行 regasm.exe,但在您的开发机器上,您可以让 VS 为您执行此操作。 Eg here:例如这里:

在此处输入图像描述

Now above does ZERO to the project - it ONLY does that regasm for you.现在上面对项目做了零 - 它只为你做那个 regasm。

At this point, then in VBA, you can use late binding, or early.此时,则在VBA中,可以使用后期绑定,也可以提前绑定。 Assuming we set a refernce in tools->reference from VBA, like this:假设我们在 tools->reference from VBA 中设置了一个引用,如下所示:

在此处输入图像描述

And now our VBA code will look like this:现在我们的 VBA 代码将如下所示:

Sub Test23434324()

  Dim cTest As New CShapeCOMTest.ComTest1
  
  Debug.Print c.HelloWorld
  
End Sub

So, I would not bother with a interface - but yours was not public.所以,我不会打扰界面 - 但你的不是公开的。

The above is all you really need for this to work.以上就是您真正需要的所有内容。 And in place of a interace, simply mark members as public or private.代替交互,只需将成员标记为公共或私有。 And this includes you dumping getters/setters.这包括你倾倒getter/setter。

You can just at the class level have this:你可以在 class 级别有这个:

public class COMTest1
    {

public string CompanyName;
public string PhoneNumber;

        public string HelloWorld
        {
            get
            {
                return "Hello, World! ";
            }
        }

    }

And those pubic members will show up in VBA intel-sense.而这些公共成员将出现在 VBA intel-sense 中。

So, I don't even bother with a interface.所以,我什至不介意界面。

I often don't bother with get/sets for simple public members (say a string)我通常不会为简单的公共成员(比如字符串)而烦恼 get/sets

As a general rule?作为基本规则? Build a simple clean class - you only add the interface tag, no GUIDS, no nothing else and no need for the interface either.构建一个简单干净的 class - 您只添加接口标签,没有 GUIDS,没有其他任何东西,也不需要接口。 Most of my classes are written this way.我的大部分课程都是这样写的。 So not much love and care required here.所以这里不需要太多的爱和关怀。

In fact, you don't even need the Classinterface tag - you can just set the make com assembly true check box in the above assembly window.事实上,您甚至不需要 Classinterface 标记 - 您只需在上述程序集 window 中设置 make com 程序集为真复选框即可。 (but, you lose intei-sense on the VBA com side if you do this ). (但是,如果你这样做,你会失去 VBA com 端的 intei-sense )。

The less code, the more we pair this down to the absolute min?代码越少,我们就越将其与绝对最小值配对?

The less code to write, and the less problems to mess this up.编写的代码越少,搞砸的问题就越少。

***Edit: ************************************ ***编辑: ************************************

The working tested example is this:工作测试的例子是这样的:

using System.Runtime.InteropServices;

[ClassInterface(ClassInterfaceType.AutoDual)]
public class COMTest1
    {

public string CompanyName;
public string PhoneNumber;

        public string HelloWorld
        {
            get
            {
                return "Hello, World! ";
            }
        }

    }

Force the project to x86.强制项目为 x86。 This will force regams.exe to correct register.这将强制 regams.exe 更正注册。 If you been running Access + testing - you have to exit access else the.dll gets locked when it runs that code.如果您一直在运行 Access + 测试 - 您必须退出访问,否则 .dll 在运行该代码时会被锁定。

Remember to set under assembly MAKE assembly COM visible.记得在组件下设置 MAKE 组件 COM 可见。

Remember to check register for com interop (build tab on project).请记住检查 com 互操作的寄存器(项目上的构建选项卡)。

With above, in VBA, you even see intel-sense like this:有了上面,在 VBA 中,你甚至会看到这样的 intel-sense:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM