【问题标题】:Method Call from ASP to .NET COM fails从 ASP 到 .NET COM 的方法调用失败
【发布时间】:2017-07-05 19:21:18
【问题描述】:

背景

我有一个用 ASP (VBScript) 编写的遗留应用程序,它调用用 VB6 编写的 COM 组件。我们正在分阶段升级,需要先将 COM 组件更新为 .NET,同时保持与 ASP 的互操作性。

情况

  1. 我创建了一个示例 .NET 类,并根据 MSDN 文档使用各种属性将其公开给 COM 系统
  2. 我可以实例化类
  3. 我可以在类上调用所需的方法

问题

  1. 参数值未发送到 COM 方法。例如所有数字类型在方法内都有值 0;所有引用类型在方法内都有空值。文字字符串被正确地传递给方法。但是,不传递字符串变量。
  2. 返回值同样的问题。无论方法返回什么值,ASP 上的变量都有默认值(0 或 null 视情况而定)。

COM 代码

<ComVisible(True)>
<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)>
Public Interface IClass1
    Function Triple(ByVal input As String) As Integer
End Interface

<ComVisible(True)>
<ProgId("TESTCOM.Class1")>
<ClassInterface(ClassInterfaceType.None)>
Public Class Class1
    Inherits ServicedComponent
    Implements IClass1

    Public Sub New()
        ' needed for COM
    End Sub

    Public Function Triple(input As String) As Integer Implements IClass1.Triple
        IO.File.WriteAllText("C:\TestCOM.Class1_Triple.log", String.Format("[{0:s}] Input: {1}", Date.Now, input)) ''' this file is updated; so I know method is being called.
        Return 97
    End Function
End Class

备用 COM 代码

<ComVisible(True)>
<ProgId("TESTCOM.Class1")>
<ComClass("E26FE8A0-8AC7-4824-9776-30ECDD473AA3")>
Public Class Class1
    'Inherits ServicedComponent
    'Implements IClass1

    Public Sub New()
        ' needed for COM
    End Sub

    Private Const LogMessageFormat As String = "[{0:s}] Input: {1}, {2}" + vbCrLf

    Public Function Triple(csinput As String, nInput As Integer) As Integer 'Implements IClass1.Triple
        IO.File.AppendAllText("C:\TestCOM.Class1_Triple.log", 
                              String.Format(LogMessageFormat, Date.Now, if(csinput isnot Nothing, csinput, "**NULL**"), nInput))
        Return 97
    End Function
End Class

ASP 代码

dim testNETCOM 
set testNETCOM = Server.CreateObject("TESTCOM.Class1")

' ** use this to check if there was any error during instantiation    
If Err.Number <> 0 Then
   Response.Redirect("http://"&Err.Description&"/")
  'Response.Write (Err.Description& "<br><br>")
else
    'Response.Redirect("http://no-error/")
End If
' ** use this to check if object is actually instantiated
if testNETCOM is nothing then
    Response.Redirect("http://no-com/")
else
    'Response.Redirect("http://yes-com/")
end if

dim nInput
set nInput = 41

dim nOutput
set nOutput = -1
set nOutput = CLng(testNETCOM.Triple("test message")) ' this string is received in the method
set nOutput = CLng(testNETCOM.Triple(CStr(nInput)))   ' this string is not received in the method

' ** use this to check if return value is what we expected
if nOutput <> 0 then
    Response.Redirect("http://test/")
else
    Response.Redirect("http://notest/") ''' **this happens**
end if

【问题讨论】:

  • 请注意 VB6 Long 类型是 .Net 类型 System.Int32 或 VB 类型 Integer。此外,如果您将ComClassAttribute 应用于类,VB.Net 编译器将帮助您创建 COM 类,而无需制作接口。
  • 关于不同数据类型的要点。我更新了代码,但问题仍然存在。
  • 我的主要观点是让编译器处理将你的类暴露给 COM,因为我比我自己更相信这些东西。无论如何,我认为你需要做的就是为你的类和接口应用一个独特的属性。为此使用 VS 工具使其变得简单。工具菜单->创建GUID->选择格式6(在VS 2013下)->复制。然后粘贴到Class上,重复界面。
  • 也试过了。不走运:(我对问题进行了编辑:文字值被很好地传递。变量被搞砸了。这适用于字符串和整数
  • 我不知道那是什么问题。我已经创建了您的 COM 类,并且能够从 VBS 和 Excel VBA 成功地使用它。我不做ASP。我建议您更新代码以显示包含 GUID 属性。祝你好运。

标签: vb.net vbscript asp-classic com vb6


【解决方案1】:

问题在于 ASP 的语法

  1. 对于简单的数据类型,不要使用'set'
  2. 对于对象,使用'set'

因为我是对简单类型使用set,所以在赋值过程中出现了错误,变量的值为null/nothing/empty。

set nInput = 41 ' this is wrong
nInput = 41     ' this is right
set nOutput = CLng(testNETCOM.Triple(CStr(nInput))) ' this is wrong
nOutput = CLng(testNETCOM.Triple(CStr(nInput)))     ' this is right

【讨论】:

    【解决方案2】:

    试一试:

    <ComVisible(True)> 
    <Guid("79571A9D-2345-48D9-8F86-7F6761A97DBA")>
    <InterfaceType(ComInterfaceType.InterfaceIsIDispatch)>
    Public Interface IClass1
        Function Triple(ByVal input As String) As Integer
    End Interface
    
    <ComVisible(True)>
    <Guid("E26FE8A0-8AC7-4824-9776-30ECDD473AA3")>
    <ProgId("TESTCOM.Class1")>
    <ClassInterface(ClassInterfaceType.None)>
    Public Class Class1
        Inherits ServicedComponent
        Implements IClass1
    
        Public Sub New()
            ' needed for COM
        End Sub
    
        Public Function Triple(input As String) As Integer Implements IClass1.Triple
            IO.File.WriteAllText("C:\TestCOM.Class1_Triple.log", String.Format("[{0:s}] Input: {1}", Date.Now, input)) ''' this file is updated; so I know method is being called.
            Return 97
        End Function
    End Class
    

    或者:

    <ComVisible(True)>
    <ProgId("TESTCOM.Class1")>
    <ComClass("E26FE8A0-8AC7-4824-9776-30ECDD473AA3", "79571A9D-2345-48D9-8F86-7F6761A97DBA")>
    Public Class Class1
        'Inherits ServicedComponent
        'Implements IClass1
    
        Public Sub New()
            ' needed for COM
        End Sub
    
        Private Const LogMessageFormat As String = "[{0:s}] Input: {1}, {2}" + vbCrLf
    
        Public Function Triple(csinput As String, nInput As Integer) As Integer 'Implements IClass1.Triple
            IO.File.AppendAllText("C:\TestCOM.Class1_Triple.log", 
                                  String.Format(LogMessageFormat, Date.Now, if(csinput isnot Nothing, csinput, "**NULL**"), nInput))
            Return 97
        End Function
    End Class
    

    【讨论】:

    • 还是没有运气。尝试其他一些选项以获取更多信息
    猜你喜欢
    • 2013-09-14
    • 1970-01-01
    • 2014-03-20
    • 2020-06-05
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多