1

Background:

I have a legacy application written in ASP (VBScript) which call COM components written in VB6. We are upgrading in phases and need to first update COM components to .NET while maintaining interoperability with ASP.

Situation:

  1. I created a sample .NET class and exposed it to COM system using various attributes as per MSDN documentation
  2. I am able to instantiate the class
  3. I am able to call the desired method on the class

Problem:

  1. Argument values are not being sent to COM method. e.g. all numeric types have value 0 inside the method; all reference types have null value inside the method. Literal strings are passed properly to the method. However, string variables are not passed.
  2. Same issue with return value. Regardless of value returned by the method, the variable on ASP has default value (0 or null as the case may be).

COM Code

<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

Alternate COM Code

<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 Code

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
6
  • Beware that the VB6 Long type is .Net Type System.Int32 or VB type Integer. Also, the VB.Net compiler will help you create your COM class without you needing to craft the interfaces if you apply the ComClassAttribute to the class. Commented Feb 16, 2017 at 15:52
  • Good point about different data types. I updated the code however, the issue remains. Commented Feb 16, 2017 at 17:04
  • My primary point was to let then compiler handle exposing your class to COM as I trust that more than myself with this stuff. Anyways, I think that all you need to do is apply a unique attribute for your class and also the interface. Use the VS tool for this to make it simple. Tools Menu->Create GUID->select format 6 (under VS 2013)->copy. Then paste on the Class, repeat for the interface. Commented Feb 16, 2017 at 17:52
  • Tried that too. No luck :( I made and edit to the question: literal values are passed fine. variables are screwed up. This applies to both strings and integers Commented Feb 16, 2017 at 18:41
  • I don't know what the issue is then. I've created your COM class and am able to successfully work with it both from VBS and Excel VBA. I don't do ASP. I suggest that you update your code to show the inclusion of the GUID attributes. Good luck. Commented Feb 16, 2017 at 19:09

2 Answers 2

2

The issue is in the syntax on ASP

  1. For simple data types, do not use 'set'
  2. For objects, use 'set'

Because I was using set for simple types, there was an error during the assignment process and the value of the variable for 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
Sign up to request clarification or add additional context in comments.

Comments

0

Give either of these a try:

<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

Or:

<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

1 Comment

Still no luck. trying a few other options to fish out more information

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.