目标:创建一个名为 TestDLL.dll 的 C# 程序集,它可以安装到任何计算机上,以便 MS Access VBA 可以通过 COM 使用它。
环境:
Windows 7 64 位。
MS Office Professional Plus 2010 版本:14.0.1753.5000(64 位)。
Visual Studio 2010 专业版。
TestDLL.dll汇编代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace TestDLL
{
[ComVisible(true)]
[Guid("7CAAEF3F-F867-445B-B078-5837A833620A")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IGreeting
{
string SayHello();
}
[ComVisible(true)]
[ProgId("TestDLL.Greeting")]
[Guid("73D4187A-F71D-4E45-832A-6DD9F88CC59B")]
[ClassInterface(ClassInterfaceType.None)]
public class Greeting : IGreeting
{
[ComVisible(true)]
public string SayHello()
{
return "Hello, World!";
}
}
}
添加到解决方案的 WinForms 项目成功调用了 SayHello() 方法。
TestDLL项目属性:
应用程序/目标框架 - .NET Framework 4
应用程序/程序集信息/使程序集 COM 可见:false(我只希望程序集中的某些公共(public)类对 COM 可见,而不是所有公共(public)类。即使对于这个演示只有一个类,我确实希望它是 COM -可见。上面的代码应该已经解决了这一点。)
Application/Assembly Information/Title and Description and Company and Product 都是“TestDLL”。
构建/平台:事件(任何 CPU)
构建/平台目标:x86
为 COM 互操作构建/注册:false(我不希望它只在我的计算机上工作,而是在所有计算机上工作。因此我想在安装时注册程序集,而不是在构建时注册。)
对程序集签名/签名:false(我希望程序集位于安装文件夹中,而不是 GAC 中。)
看一眼 AssemblyInfo.cs 就会发现:
[assembly: ComVisible(false)]
[assembly: Guid("6bf701f9-3953-43bb-a8af-1bdf7818af3c")]
程序集已构建。
然后使用 Visual Studio 命令提示符(以管理员身份运行)和以下命令创建类型库:
tlbexp "C:\(path)\bin\Release\TestDLL.dll" /win32 /out:"C:\(path)\bin\Release\TestDLL.tlb"
名为 SetupTestDLL 的 Visual Studio 安装程序项目已添加到解决方案中。
在其文件系统选项卡上,应用程序文件夹中添加了 TestDLL.dll。这也会自动添加 TestDLL.tlb。
右键单击该应用程序文件夹中的 TestDLL.dll 允许打开属性窗口。
在那里,注册:vsdraCOM
右键单击该应用程序文件夹中的 TestDLL.tlb 以获取属性窗口时:
注册:vsdrfCOM
(我猜 vsdraCOM 意味着注册程序集,而 vsdrfCOM 意味着为 COM 注册一个文件。)
Application 文件夹中又添加了一个文件:TestDLL.pdb。
SetupTestDLL 已构建。 浏览到其输出文件夹,显示 setup.exe 和 setupTestDLL.msi。 右键单击 setup.exe 并以管理员身份运行。 一个对话框显示正确的安装路径和正确的“为所有人安装”选项。 安装成功完成。
在控制面板/程序和功能中,现在列出了 TestDLL。它的出版商被列为“XYZ”。那个是从哪里来的?从 SetupTestDLL 项目属性窗口的“Manufacturer”属性可以看出。我只在整个解决方案中创造了那个值(value)。
在 C:\Program Files (x86) 中现在有一个“XYZ”文件夹,在该文件夹下是一个 TestDLL 文件夹,里面是三个文件。
启动 MS Access。打开现有数据库及其现有代码模块。 从访问代码窗口工具栏中,选择工具/引用。 TestDLL 位于可用引用列表框中。单击其复选框并单击确定。
单击代码窗口工具栏上的“对象浏览器”按钮。
在下拉列表中选择。将其更改为 TestDLL。
类“Greeting”与其方法“SayHello”一起显示。到目前为止,还不错。
关闭对象浏览器。
在代码模块中创建此过程并尝试运行它。
Public Sub Test2()
' Dim o As New TestDLL.Greeting
' The above is early binding. It should also work
' since we set a reference.
Dim o As Variant
Set o = CreateObject("TestDLL.Greeting")
' The above is late binding.
Debug.Print o.SayHello()
Set o = Nothing
End Sub
结果: 无论是早绑定(bind)还是晚绑定(bind), ActiveX 组件无法创建对象。
怎么了?
最佳答案
我只是想添加评论,但我没有足够的声誉点数,所以我只是将其发布为答案并在必要时将其删除。
我不熟悉 Visual Studio 安装程序项目,所以我不确定它是否正确注册了程序集。您是否尝试过使用 regasm 注册 TestDLL?像这样的东西:
regasm /codebase TestDLL.dll /tlb:TestDLL.tlb
关于c# - 无法创建 C# COM DLL。是代码吗?项目属性?安装程序属性? 32-64 位?什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32339928/