繁体   English   中英

如何在 Microsoft Access 中使用 C# DLL

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

我在 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! "; } }
    }
}

代码编译良好,我可以在 VBA 中引用它,属性“Hello World”显示在 object 浏览器的 class“测试”中。

但是,当我尝试使用代码访问 onClick 事件子例程时

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

错误:'429'“ActiveX 组件无法创建对象”在 Set o = New Test 处生成。

我究竟做错了什么?

嗯,首先? 您没有将接口标记为公开

例如;

    public interface _Test

接下来,我将删除 Prog_id - 你不需要它,我认为这也会搞砸。

而且,真的,我看不出有什么理由在这里建立一个接口? 我怀疑在 c# (或者肯定在 VBA 中),你不需要声明从 class 派生的公共成员变量类型,而不必创建 class 的实例,然后我想你需要可以做一个接口的案例,但是其他的那么这个原因吗?不需要)。

也不需要担心代码中的 GUIDS。 项目设置将解决这个问题。

而且您实际上并不需要命名空间 - 项目默认会再次处理这个问题。

所以,现在我们归结为:

using System.Runtime.InteropServices;

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

    }

好的,现在好多了,当然:我们需要在这里选中“com visible”框:

在此处输入图像描述

或者您可以在 class 接口类型设置上方添加一个 COMvisible=true。

在开发过程中,您可以(应该)注册 COM 程序集。 在目标机器上,您必须执行 regasm.exe,但在您的开发机器上,您可以让 VS 为您执行此操作。 例如这里:

在此处输入图像描述

现在上面对项目做了零 - 它只为你做那个 regasm。

此时,则在VBA中,可以使用后期绑定,也可以提前绑定。 假设我们在 tools->reference from VBA 中设置了一个引用,如下所示:

在此处输入图像描述

现在我们的 VBA 代码将如下所示:

Sub Test23434324()

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

所以,我不会打扰界面 - 但你的不是公开的。

以上就是您真正需要的所有内容。 代替交互,只需将成员标记为公共或私有。 这包括你倾倒getter/setter。

你可以在 class 级别有这个:

public class COMTest1
    {

public string CompanyName;
public string PhoneNumber;

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

    }

而这些公共成员将出现在 VBA intel-sense 中。

所以,我什至不介意界面。

我通常不会为简单的公共成员(比如字符串)而烦恼 get/sets

作为基本规则? 构建一个简单干净的 class - 您只添加接口标签,没有 GUIDS,没有其他任何东西,也不需要接口。 我的大部分课程都是这样写的。 所以这里不需要太多的爱和关怀。

事实上,您甚至不需要 Classinterface 标记 - 您只需在上述程序集 window 中设置 make com 程序集为真复选框即可。 (但是,如果你这样做,你会失去 VBA com 端的 intei-sense )。

代码越少,我们就越将其与绝对最小值配对?

编写的代码越少,搞砸的问题就越少。

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

工作测试的例子是这样的:

using System.Runtime.InteropServices;

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

public string CompanyName;
public string PhoneNumber;

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

    }

强制项目为 x86。 这将强制 regams.exe 更正注册。 如果您一直在运行 Access + 测试 - 您必须退出访问,否则 .dll 在运行该代码时会被锁定。

记得在组件下设置 MAKE 组件 COM 可见。

请记住检查 com 互操作的寄存器(项目上的构建选项卡)。

有了上面,在 VBA 中,你甚至会看到这样的 intel-sense:

在此处输入图像描述

暂无
暂无

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

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