简体   繁体   English

无法创建C#COM DLL。 是代码吗? 项目属性? 安装程序属性? 32-64位? 什么?

[英]Can't create C# COM DLL. Is it the code? Project properties? Installer properties? 32-64 bit? What?

Goal: Create a C# Assembly called TestDLL.dll that can be installed to any computer such that MS Access VBA can use it via COM. 目标:创建一个名为TestDLL.dll的C#程序集,该程序集可以安装到任何计算机上,以便MS Access VBA可以通过COM使用它。

Environment: Windows 7 64-bit. 环境:Windows 7 64位。
MS Office Professional Plus 2010 Version: 14.0.1753.5000 (64-bit). MS Office Professional Plus 2010版本:14.0.1753.5000(64位)。
Visual Studio 2010 Professional. Visual Studio 2010专业版。

TestDLL.dll assembly code: 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!";
        }
    }
}

A WinForms project added to the solution successfully calls the SayHello() method. 添加到解决方案中的WinForms项目成功调用了SayHello()方法。

TestDLL project properties: TestDLL项目属性:
Application / Target Framework - .NET Framework 4 应用程序/目标框架-.NET Framework 4
Application / Assembly Information / Make assembly COM-visible: false (I only want certain public classes within the assembly to be COM-visible, not ALL public classes. Even though for this demo there's just one class and I do want it to be COM-visible. The code above should have taken care of that.) 应用程序/程序集信息/使程序集成为COM可见的:false(我只希望程序集中的某些公共类对COM可见,而不是所有公共类。尽管对于本演示来说,只有一个类并且我确实希望它成为COM -visible。上面的代码应该已经解决了。)
Application / Assembly Information / Title and Description and Company and Product are all "TestDLL". 应用程序/组装信息/标题和描述以及公司和产品均为“ TestDLL”。
Build / Platform: Active (any CPU) 构建/平台:活动(任何CPU)
Build / Platform target: x86 构建/平台目标:x86
Build / Register for COM interop: false (I don't want it to work on MY computer only but ALL computers. Thus I want to register the assembly when it is INSTALLED, not when it is BUILT.) 为COM互操作生成/注册:false(我不希望它仅在我的计算机上工作,而是在所有计算机上工作。因此,我想在安装时(而不是在构建时)注册程序集。
Signing / Sign the assembly: false (I want the assembly to live in the install folder, not in the GAC.) 对程序集签名/签名:false(我希望程序集位于安装文件夹中,而不是在GAC中。)

A peek at AssemblyInfo.cs reveals: 窥视AssemblyInfo.cs会发现:

[assembly: ComVisible(false)]
[assembly: Guid("6bf701f9-3953-43bb-a8af-1bdf7818af3c")]

The assembly is built. 程序集已建立。 Then a type library is created using the Visual Studio Command Prompt (run as Administrator) with this command: 然后使用Visual Studio命令提示符(以管理员身份运行)通过以下命令创建类型库:

tlbexp "C:\(path)\bin\Release\TestDLL.dll" /win32 /out:"C:\(path)\bin\Release\TestDLL.tlb"

A Visual Studio Installer project called SetupTestDLL is added to the solution. 名为SetupTestDLL的Visual Studio安装程序项目已添加到解决方案中。
On its File System tab, Application Folder, TestDLL.dll is added. 在其文件系统选项卡上,添加应用程序文件夹TestDLL.dll。 This automatically also adds TestDLL.tlb. 这还将自动添加TestDLL.tlb。
Right-clicking TestDLL.dll in that Application Folder allows opening a properties window. 右键单击该应用程序文件夹中的TestDLL.dll可以打开属性窗口。 There, Register: vsdraCOM 在那里,注册:vsdraCOM
When right-clicking TestDLL.tlb in that Application folder to get the properties window: 右键单击该“应用程序”文件夹中的TestDLL.tlb以获取属性窗口时:
Register: vsdrfCOM 注册:vsdrfCOM
(I'm guessing that vsdraCOM means register the assembly and vsdrfCOM means register a file for COM.) (我猜测vsdraCOM表示注册程序集,而vsdrfCOM表示注册COM文件。)
One more file is added to the Application folder: TestDLL.pdb. 另一个文件添加到应用程序文件夹:TestDLL.pdb。

SetupTestDLL is built. SetupTestDLL已构建。 Browsing to its output folder, reveals setup.exe and setupTestDLL.msi. 浏览到其输出文件夹,显示setup.exe和setupTestDLL.msi。 Right-click setup.exe and Run as administrator. 右键单击setup.exe,然后以管理员身份运行。 A dialog box displays the correct install path and the correct "Install for everyone" option. 对话框显示正确的安装路径和正确的“为所有人安装”选项。 The install completes successfully. 安装成功完成。

In the Control Panel / Programs and Features, TestDLL is now listed. 在控制面板/程序和功能中,现在列出了TestDLL。 Its publisher is listed as "XYZ". 其发布者被列为“ XYZ”。 Where did that come from? 那个是从哪里来的? Evidently from the "Manufacturer" property of the SetupTestDLL project's property window. 显然是从SetupTestDLL项目的属性窗口的“制造商”属性中获得的。 I created that value only there in the entire solution. 我仅在整个解决方案中在那里创建了该值。

In C:\\Program Files (x86) there is now an "XYZ" folder, under which is a TestDLL folder, and in that are the three files. 在C:\\ Program Files(x86)中,现在有一个“ XYZ”文件夹,在该文件夹下是一个TestDLL文件夹,并且这是三个文件。

Launch MS Access. 启动MS Access。 Open an existing database and its existing code module. 打开一个现有的数据库及其现有的代码模块。 From the Access code window toolbar, choose Tools / References. 在访问代码窗口工具栏中,选择“工具/引用”。 TestDLL is found in the Available References listbox. 在“可用参考”列表框中找到TestDLL。 Click its check box and click OK. 单击其复选框,然后单击确定。

Click the Object Browser button on the code window toolbar. 单击代码窗口工具栏上的“对象浏览器”按钮。 is selected in a dropdown list. 在下拉列表中被选中。 Change it to TestDLL. 将其更改为TestDLL。 The class "Greeting" is shown with its method "SayHello". 显示的类“问候”及其方法“ SayHello”。 So far, so good. 到现在为止还挺好。
Close the Object Browser. 关闭对象浏览器。
Create this procedure in the code module and try to run it. 在代码模块中创建此过程,然后尝试运行它。

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

Result: Whether early or late bound, ActiveX Component can't create object. 结果:无论是早期绑定还是后期绑定,ActiveX组件都无法创建对象。

What's wrong? 怎么了?

I was just going to add a comment, but I don't have enough reputation points so I'll just post this as an answer and remove it if necessary. 我只是要添加评论,但我没有足够的声誉点,因此我将其发布为答案,并在必要时将其删除。

I'm not familiar with Visual Studio Installer projects, so I'm not sure if it is registering the assembly correctly. 我不熟悉Visual Studio Installer项目,因此不确定它是否正确注册了程序集。 Have you tried using regasm to register TestDLL? 您是否尝试过使用regasm注册TestDLL? Something like: 就像是:

regasm /codebase TestDLL.dll /tlb:TestDLL.tlb

64-bit MS Office cannot use a 32-bit COM DLL early bound, but with a reg hack involving DLLSurrogate, it can use it late-bound. 64位MS Office不能使用32位COM DLL的早期绑定,但是通过涉及DLLSurrogate的注册表破解,它可以后期绑定使用。 I got that to work. 我明白了。

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

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