从Office 2003执行.NET 3.0代码

8

我使用 .NET 3.0 框架用 C# 创建了一个 DLL。

下面是我的 DLL 代码:

namespace CompanyName.Net
{
    [Guid("F7075E8D-A6BD-4590-A3B5-7728C94E372F")]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [ProgId("CompanyName.Net.Webrequest")]
    public class WebRequest
    {
        public string Result { get; private set; }
        public string Url { get; set; }
        public string StatusDescription { get; private set; }
        public HttpStatusCode StatusCode { get; private set; }

        public WebRequest()
        {
            //explicit constructor
        }    

        public string GetResponse(string url)
        {
            System.Net.WebRequest webreq = System.Net.WebRequest.Create(url);
            HttpWebResponse response = (HttpWebResponse) webreq.GetResponse();
            // Store the status.
            StatusDescription = response.StatusDescription;
            StatusCode = response.StatusCode;
            // Get the stream containing content returned by the server.
            Stream dataStream = response.GetResponseStream();
            // Open the stream using a StreamReader for easy access.
            StreamReader reader = new StreamReader(dataStream);
            // Read the content.
            Result = reader.ReadToEnd();
            // Cleanup the streams and the response.
            reader.Close();
            dataStream.Close();
            response.Close();
            //return the response
            return Result;
        }
    }
}

我正在尝试从Office 2003 VBA代码中运行此代码。该DLL使用默认的Visual Studio 2008签名进行签名。

我已经成功通过创建.TLB文件来引用我的程序集

regasm /tlb c:\CompanyName.Net.dll 

但是当我想要创建对象的实例时:
Private Sub Command0_Click()
    Dim o As Object
    Set o = CreateObject("CompanyName.Net.WebRequest")
    Dim s As String
    s = o.GetResponse("http://www.google.be")
    MsgBox s
End Sub

我遇到了以下错误:

ActiveX组件无法创建对象

我做错了什么?

我测试的机器上已安装.NET框架,版本为.NET 3.5。

2个回答

11

好的,在Thorsten Dittmar提供了一些非常好的想法后,我终于让这个东西运作起来了。在我们的讨论中出现了一些问题以及其他我在网上找到的东西:

  1. 目标机器上需要安装.NET框架。
  2. 目标机器上需要安装.Net可编程性支持。
  3. 在AssemblyInfo.cs中,请确保您设置了

    [assembly: ComVisible(true)]

  4. 正如Thorsten所指出的,您需要在.NET类中拥有无参数的公共构造函数。

  5. 请确保在项目属性的生成选项卡中勾选“为COM互操作注册”。
  6. 请确保使用项目属性的签名选项卡对您的项目进行签名。
  7. 通过运行此命令在目标计算机上注册您的DLL。对我而言,/codebase参数似乎起到了作用。类型库(.tlb)或DLL的路径不重要。您可以在C:\Windows\Microsoft.Net\Framework\v2.050727\RegAsm.exe找到regasm。

    regasm c:\CompanyName.Net.dll /tlb:CompanyName.Net.tlb /codebase

  8. 在VBA编辑器中使用“工具”>“引用”引用.tlb文件。

  9. 将dll从C:\拖到您的GAC中,位于C:\Windows\assembly\ (我起初没有意识到这一点,但显然这对于Office找到您的程序集是必要的。)

应该就可以了。

我还通过为Webrequest类添加接口来升级它,从而在VB6中启用了IntelliSense支持(遗憾的是,在VBA中无法使用)。


1
这是我在尝试多个小时后找到的最简明且唯一完整的解决方案指南。非常感谢。 - Evil Pigeon

2
您的COM类需要一个显式的无参数构造函数。请修改您的类定义如下:

namespace CompanyName.Net
{
    [Guid("F7075E8D-A6BD-4590-A3B5-7728C94E372F")]
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [ProgId("CompanyName.Net.Webrequest")]
    public class WebRequest
    {
        public string Result { get; private set; }
        public string Url { get; set; }
        public string StatusDescription { get; private set; }
        public HttpStatusCode StatusCode { get; private set; }

        public WebRequest()
        {
        }

        public string GetResponse(string url)
        {
            System.Net.WebRequest webreq = System.Net.WebRequest.Create(url);
            HttpWebResponse response = (HttpWebResponse) webreq.GetResponse();
            // Store the status.
            StatusDescription = response.StatusDescription;
            StatusCode = response.StatusCode;
            // Get the stream containing content returned by the server.
            Stream dataStream = response.GetResponseStream();
            // Open the stream using a StreamReader for easy access.
            StreamReader reader = new StreamReader(dataStream);
            // Read the content.
            Result = reader.ReadToEnd();
            // Cleanup the streams and the response.
            reader.Close();
            dataStream.Close();
            response.Close();
            //return the response
            return Result;
        }
    }
}

这应该可以正常工作。


我刚刚尝试了一下,但它仍然给我同样的错误。我将我的项目标记为“注册COM互操作”,但没有成功。也许我在VBA中调用函数的方式是错误的?我很困惑。 - Peter
我重新创建了tlb文件,这应该也会重新注册dll。 我可以再尝试将它添加到GAC吗? - Peter
此外,将一些代码包装在try/catch块中并以不同方式处理错误可能会有所帮助(不知道VBA代码是否能够优雅地处理异常)。当我需要做类似的事情时,我会返回一个指示成功或失败的整数,并设置一个“ref”参数来存储错误消息。 - Thorsten Dittmar
不需要将其放入全局程序集缓存(GAC) - 实际上,在测试时,我会删除GAC条目。也许由于GAC条目,新版本甚至没有被使用? - Thorsten Dittmar
嗯,那我对于在.NET中使用COM互操作所知道的就到这里了。我还想到两件事:1)重新添加到全局程序集缓存(GAC),或许有所帮助;2)在使用.NET编写Office插件时,需要确保安装了Office的.NET支持 - 或许这就是问题所在?否则,我无法在此时提供更多帮助。 - Thorsten Dittmar
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接