使用4.0框架和Visual Studio 2010为ASP Classic构建COM互操作库

8

在阅读了许多不太确定的文章后,我并没有找到任何一篇文章可以逐步指导我完成这个过程,因此我来寻求帮助。

情况

我的客户只熟悉ASP Classic开发。他们最近获得了一个原本用ASP.NET编写的网站的账户。他们正在将该网站转换为他们可以积极维护的东西,但是该网站最初包含一个图像处理程序,该程序获取动态变化的水位数据并输出包含该数据图形表示的图像。要求开发一个COM互操作库,可以在服务器上注册并使用CreateObject调用以生成相同图像的字节数组,然后使用Response.BinaryWrite进行输出。该COM互操作库必须在Windows 2000 Server上的远程站点上注册,我不能假设他们有访问regasm/gacutil的权限来完成该任务。

困难之处

我已经通过在Visual Studio 2010中创建一个“Class Library”项目,选择“COM Class”模板,并插入我的代码来生成一个类,该类具有一个公共方法,当给定一个整数(实际上是枚举)时返回一个字节数组,来构建了类库。不幸的是,即使在我的开发机器上构建了库并注册(regasm)和缓存了程序集(gacutil),我也无法通过Classic ASP进行调用以实例化对象,而是收到一个“ActiveX component can't create object”错误。当然,在服务器端,DLL文件也无法注册,响应是“找不到所需的模块”。 我使用过的资源 我已经查看了以下文章,但没有找到我需要的答案:
  1. (基本步骤) 使用Visual Basic创建COM对象的演练
  2. 构建和部署.NET COM程序集
  3. .NET COM+互操作组件与经典ASP

我需要什么

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

然而,我查阅的文章中没有讨论使用Visual Studio 2010或.NET 4.0框架的项目选项或构建程序,也没有讨论在部署到旧系统(如Windows Server 2000)时是否有特殊考虑以及在只有regsvr32的系统上注册库的实际情况。请注意保留HTML标签。

对于所有后来者:在做更多的功课后,我想在这里指出,我还需要将我的库针对 .NET 2.0 Framework 进行定位,因为这是 Windows Server 2000 支持的最新框架。 - lsuarez
2个回答

14

将一个基本的.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中保持部署更简单),请确保使用-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所做的重要工作是将各种设置写入注册表,以便客户端可以根据Prog ID或COM Class ID找到COM组件。您只需要确定在本地计算机上运行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中的模板处理,因此这部分至少很方便。我在过去的构建中也处理了强名称密钥,因为许多评论/文章提到它是必需的。我认为区别在于我不知道 [ProgId("Test.Comm.1")] 将是我需要调用的程序集上的标签。这可能会对我有很大帮助!如果您非常详细的帮助已经得到了验证,我一定会尽快告诉您。 - lsuarez
具有讽刺意味的是,我最终解决了这个问题,但 Win2k 服务器被 Win 2k8 箱取代了,所以我们将在 .NET 中放置一个 ASHX 处理程序与 ASP 并行。无论如何,在我的开发机上运行事情方面,你帮我解决了这个问题。:] - lsuarez
3
关于这个答案最后部分提到的创建注册表项的问题:Regasm有一个开关/regfile,它不会更新注册表,但允许你将它将要做出的更改写入一个文件。 - PeskyGnat

2
我有一个使用VB6 COM对象的Classic 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

  • Add a new "COM class", name it "HelloCOM".
  • VB.NET creates the starting template.
  • Add the following function to the "HelloCOM" class.

    Public Function Hello() As String
        Return "Hello there!"
    End Function
    
[03] C#:
  • 打开项目属性。
  • 进入“应用程序”。
  • 点击“程序集信息…”。
  • 勾选“使程序集可见于COM”。
  • 进入“生成”。
  • 选择“平台目标:x86”。
  • 勾选“为互操作注册COM”。
[03] VB.NET:
  • 打开“MyProject”。
  • 进入“编译”。
  • 选择“目标CPU:x86”。
[04]:
  • 构建“DotNetCom.dll”。
[05]:
  • Open a command prompt (run as admin).
  • Change directory to your dll.

    cd DotNetComTest\DotNetComTest\TX7NGN.COM\bin\Debug
    
  • Run 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]
  • Use the COM object from the Classic ASP page.

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

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