【问题标题】:Building a COM interop library for ASP Classic using 4.0 framework and Visual Studio 2010使用 4.0 框架和 Visual Studio 2010 为 ASP Classic 构建 COM 互操作库
【发布时间】:2021-11-02 19:23:00
【问题描述】:

在阅读了许多不同的文章后,没有发现任何特别有说服力的东西可以让我逐步完成整个过程,我来寻求帮助。

情景

我的一个客户只精通ASP Classic 的开发。他们最近获得了一个最初用 ASP.NET 编写的网站的帐户。他们正在将站点滚动到可以积极维护的位置,但该站点最初包含一个图像处理程序,该处理程序获取有关水位的动态变化数据并输出包含该数据的图形表示的图像。要求是开发一个COM 互操作库,可以在服务器上注册并使用 CreateObject 调用以生成相同的图像字节数组以使用Response.BinaryWrite 输出。 COM 互操作库必须在 Windows 2000 Server 上的远程站点上注册,我无法假设他们可以访问 regasm/gacutil 来完成该任务。

难度

我通过在 Visual Studio 2010 中创建一个类库项目来构建类库,从模板中选择“COM 类”,然后插入我的代码以生成具有单个公共方法的类当给定一个整数时返回一个字节数组(好吧,枚举器,但都一样)。不幸的是,即使在我自己的开发机器上构建库并注册(regasm)和缓存程序集(gacutil)之后,我也无法通过经典 ASP 调用来实例化对象,而是接收到“ActiveX 组件可以” t 创建对象”错误。而且,当然,在服务器站点,无法注册 DLL 文件,响应是“找不到所需的模块”。

我使用过的资源

我已经浏览了以下文章,但没有找到我需要的答案:

  1. (基本步骤)Walkthrough: Creating COM Objects with Visual Basic
  2. Build and Deploy a .NET COM Assembly
  3. .NET COM+ Interop Component with Classic ASP

我需要什么

基本上,我需要的是一点点手把手地逐步了解满足要求并在 Visual Studio 2010 中正确创建 COM+ 互操作模块。创建实际的类对象本身并不难。

但是,我浏览过的所有文章都没有真正讨论使用 Visual Studio 2010 或 .NET 4.0 框架的项目选项或构建过程,也没有任何文章真正讨论过部署到旧系统时是否有特殊考虑,例如Windows Server 2000 和库在系统上的实际注册,例如,手头只有 regsvr32

【问题讨论】:

  • 对于所有落后的人:在做更多功课后,我想在这里指出,我还需要将我的库定位到 .NET 2.0 框架,因为这是 Windows 支持的最新框架服务器 2000。

标签: asp.net visual-studio-2010 .net-4.0 asp-classic com-interop


【解决方案1】:

我有一个使用 VB6 COM 对象的经典 ASP 网站。我想使用 .NET 而不是 VB6 创建新版本的 COM 对象。我就是这样做的(希望这会有所帮助)。我包括 C# 和 VB.NET 的说明。

[01]

  • 启动 Visual Studio 2015(以管理员身份运行)。
  • 创建一个新的“类库”项目。
  • 将其命名为:“DotNetCom”

[02] C#

  • 添加一个新类,将其命名为“HelloCOM”。
  • 使用以下代码作为起始模板

(访问https://msdn.microsoft.com/en-us/library/c3fd4a20.aspx了解更多信息)

    using System.Runtime.InteropServices;

    namespace DotNetCom
    {
        [Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")]
        public interface HelloCOMInterface
        {
            [DispId(1)]
            string Hello();
        }

        [Guid("7BD20046-DF8C-44A6-8F6B-687FAA26FA71"), 
            InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
        public interface HelloCOMEvents 
        {
        }

        [Guid("0D53A3E8-E51A-49C7-944E-E72A2064F938"),
            ClassInterface(ClassInterfaceType.None),
            ComSourceInterfaces(typeof(HelloCOMEvents))]
        public class HelloCOM : HelloCOMInterface
        {
            public string Hello()
            {
                return "Hello there!";
            }
        }
    }

[02] VB.NET

  • 添加一个新的“COM 类”,将其命名为“HelloCOM”。
  • VB.NET 创建起始模板。
  • 将以下函数添加到“HelloCOM”类中。

    Public Function Hello() As String
        Return "Hello there!"
    End Function
    

[03] C#

  • 打开项目属性。
  • 转到“应用程序”。
  • 点击“程序集信息...”。
  • 选中“使程序集 COM 可见”
  • 转到“构建”。
  • 选择“平台目标:x86”。
  • 选中“为互操作注册 COM”

[03] VB.NET

  • 打开“我的项目”。
  • 转到“编译”。
  • 选择“目标 CPU:x86”。

[04]

  • 构建“DotNetCom.dll”。

[05]

  • 打开命令提示符(以管理员身份运行)。
  • 将目录更改为您的 dll。

    cd DotNetComTest\DotNetComTest\TX7NGN.COM\bin\Debug
    
  • 运行 RegAsm /codebase。

    C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm DotNetComTest.dll /codebase "C:\DotNetComTest\DotNetComTest\bin\Debug\DotNetComTest.dll"
    

[06]

  • 启动组件服务。
  • 添加新的 COM+ 应用程序。
  • 将其命名为:“DotNetCom”。
  • 打开“DotNetCom”属性。
  • 转到“安全选项卡”。
  • 取消选中“对此应用程序执行访问检查”。

[07]

  • 添加一个新组件。
  • 选择“DotNetComTest.tlb”(不要选择“DotNetComTest.dll”)。

[08]

  • 使用经典 ASP 页面中的 COM 对象。

    <%
    Dim HelloCOM
    Set HelloCOM = Server.CreateObject("DotNetCom.HelloCOM")
    Response.Write HelloCom.Hello
    %>
    

【讨论】:

    【解决方案2】:

    将基本的 .NET 程序集暴露给 COM 应该相当简单 - 我从未尝试过 COM 类项目模板,所以这是我过去管理它的方式:

    使用 C# 或 VB 创建一个新的(沼泽标准).NET 类库。定义一个 COM 接口(用您自己的 GUID 替换):

    [ComVisible(true)]
    [Guid("8999F93E-52F6-4E29-BA64-0ADC22A1FB11")]
    public interface IComm
    {
        string GetMyGroups();
    }
    

    现在定义一个实现该接口的类(同样,用您自己的 GUID 替换):

    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    [GuidAttribute("C5C5A1A8-9BFB-4CE5-B42C-4E6688F6840B")]
    [ProgId("Test.Comm.1")]
    public class Comm : IComm
    {
        public string GetMyGroups()
        {
            var comm = new CommunicatorAPI.MessengerClass();
    
            var groups = comm.MyGroups as IMessengerGroups;
            return string.Join(", ", groups.OfType<IMessengerGroup>().Select(g => g.Name).ToArray());
        }
    }
    

    这个类的 Prog ID 属性是您将用来从 ASP 实例化您的组件的属性。

    强命名程序集(项目属性 -> “签名”选项卡 -> “签署程序集” -> 使用下拉菜单创建新的强名称密钥文件)

    现在,构建程序集,并使用 Regasm 注册 - 如果您不想在 GAC 中注册(我建议您这样做,因为不是 GACing 会使部署更简单),请务必使用 -Codebase参数(这只是添加一个 reg 条目,告诉客户端在哪里可以找到程序集) - 例如:

    regasm ClassLibrary2.dll /codebase "S:\Testing\ClassLibrary2\ClassLibrary2\bin\Debug\ClassLibrary2.dll"
    

    现在您应该能够实例化组件,并在其上调用方法 - 例如(在 javascript 中):

    var a = new ActiveXObject("Test.Comm.1");
    alert(a.GetMyGroups());
    

    在部署方面,Regasm 和 Regsvr32 做的重要工作是将各种设置写入注册表,以便客户端可以找到 COM 组件(基于 Prog ID,或 COM Class ID)。您需要做的就是弄清楚当您在本地计算机上运行 Regasm 时正在写入哪些 COM 设置,并将这些设置写入服务器上的注册表。您可以使用ProcMon 来监控 Regasm 运行时写入注册表的内容。

    一般来说,您可以期望看到这样的内容写入注册表:

    [HKEY_CLASSES_ROOT\Test.Comm.1]
    @="ClassLibrary2.Comm"
    
    [HKEY_CLASSES_ROOT\Test.Comm.1\CLSID]
    @="{00585504-90C8-4760-A359-67CAF08FFED1}"
    
    [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{00585504-90C8-4760-A359-67CAF08FFED1}]
    @="ClassLibrary2.Comm"
    
    [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{00585504-90C8-4760-A359-67CAF08FFED1}\Implemented Categories]
    
    [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{00585504-90C8-4760-A359-67CAF08FFED1}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}]
    
    [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{00585504-90C8-4760-A359-67CAF08FFED1}\InprocServer32]
    @="mscoree.dll"
    "ThreadingModel"="Both"
    "Class"="ClassLibrary2.Comm"
    "Assembly"="ClassLibrary2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cf55d4e60653257a"
    "RuntimeVersion"="v4.0.30319"
    "CodeBase"="file:///S:/Testing/ClassLibrary2/ClassLibrary2/bin/Debug/ClassLibrary2.DLL"
    
    [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{00585504-90C8-4760-A359-67CAF08FFED1}\InprocServer32\1.0.0.0]
    "Class"="ClassLibrary2.Comm"
    "Assembly"="ClassLibrary2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cf55d4e60653257a"
    "RuntimeVersion"="v4.0.30319"
    "CodeBase"="file:///S:/Testing/ClassLibrary2/ClassLibrary2/bin/Debug/ClassLibrary2.DLL"
    
    [HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{00585504-90C8-4760-A359-67CAF08FFED1}\ProgId]
    @="Test.Comm.1"
    

    希望这会有所帮助:)

    【讨论】:

    • 非常感谢。 COM 类包装器由 VS2010 中的模板处理,因此至少这部分很方便。我在过去的构建中也处理了强名称键,因为很多 cmets/文章都提到它是必需的。我认为区别在于我不知道 [ProgId("Test.Comm.1")] 将是我需要调用的程序集上的标签。这可能对我有很大帮助!如果您的彻底帮助尽快得到解决,我一定会通知您。
    • 好吧,具有讽刺意味的是,与此同时,我终于解决了这个问题,Win2k 服务器被 Win 2k8 机器所取代,所以我们将在 .NET 中并排放置一个 ASHX 处理程序与 ASP。但是,就在我的开发机器上运行而言,您帮助我解决了这个问题。 :]
    • 参考这个答案的最后一部分,关于创建的注册表项:Regasm 有一个开关 /regfile 不会更新注册表,但允许您将它所做的更改写入文件。
    猜你喜欢
    • 2011-02-14
    • 2012-02-27
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 2018-05-10
    • 1970-01-01
    • 2011-02-09
    相关资源
    最近更新 更多