Link to home
Start Free TrialLog in
Avatar of kkandasa
kkandasa

asked on

Runtime 430 Error

Hi,

I have written an ActiveX dll which I have problems running
in a test client workstation.
I get the error;
{Runtime 430: CLASS DOES NOT SUPPORT AUTOMATION OR DOES NOT SUPPORT EXPECTED INTERFACE}

1) I had played around with the interfaces and methods in the course of testing this ActiveX dll in my PC.

2) When I was done, I switched the version compatiblity option under ProjectProperties/component tab to No compatibility option.
3) I compiled the dll, copied to the client PC,
unregistered the previous version and registered this version.

4) I wrote a sample vb client app to test it. When running
it, I got the error.

5) As easy as ActiveX dll was to write and test, deploying
it in other computers seems to be complicated. What am I
missing ?

ActiveX client sample code:
=================================
Private Sub Form_Load()
    test1
End Sub

Private Sub test1()
    Dim MySQL As PulseDbase.pDirectSQL
   
    Set MySQL = New PulseDbase.pDirectSQL
    MySQL.FieldSeperator = "|"
    MySQL.DbaseName = "metrics_tst"
   
    MySQL.DSN = "TAZ"
    MySQL.SQLString = "Select * from t_kandy"
    MySQL.RecordsReturnFlag = True
    MySQL.UserID = "sa"
    MySQL.ParameterTotal = 0
    MySQL.RequiredRowNumber = 2
    MySQL.Password = ""
    If MySQL.Execute <> 0 Then //ERROR HERE
        Debug.Print MySQL.ErrorString //ERROR STRING WITH RUNTIME 430 message
        Debug.Print MySQL.ActualSQL
    End If
   
    Debug.Print MySQL.RowTotal
    Debug.Print MySQL.ColumnTotal
    Debug.Print MySQL.RowInfo
   
    Set MySQL = Nothing
   
    Exit Sub
End Sub



=================================

ActiveX dll sample code:
==========================================
Option Explicit
'properties to be populated by client
Public DSN As String        'data source name
Public UserID As String     'user id for login
Public Password As String   'password for login
Public DbaseName As String  'database name
Public SQLString As String  'sql string to be executed
Public ParameterTotal As Integer 'number of parameters to be used by query
Public RecordsReturnFlag As Boolean  'Flag indicating if records are returned
Public RequiredRowNumber As Integer 'Required row of recordset
Public FieldSeperator As String  'seperator for fields returned

'properties to be populated by this ActiveX object
Public ColumnTotal As Integer   'Total number of columns from query
Public RowTotal As Integer      'Total number of records from query
Public RowInfo As String        'Contains single record information
Public ErrorString As String    'Contains error message if needed

'private properties
Private MySQLString As String
Private ParameterType(1 To 15) As String
Private ParameterValue(1 To 15) As String
Private MyConn As ADODB.Connection
Private MyCommand As ADODB.Command
Private MyRset As ADODB.Recordset
Private MyConnCleanupFlag As Boolean
Private MyRsetCleanupFlag As Boolean
Property Get ActualSQL()
    ActualSQL = MySQLString
End Property
Property Let ParmType(idx As Integer, val1 As String)
    If idx >= 0 And idx <= 15 Then
        ParameterType(idx) = val1
    End If
End Property
Property Let ParmValue(idx As Integer, val1 As String)
    If idx >= 0 And idx <= 15 Then
        ParameterValue(idx) = val1
    End If
End Property


Private Sub Class_Initialize()
    'Initialize properties to be populated by client
    DSN = ""
    UserID = ""
    Password = ""
    DbaseName = ""
    SQLString = ""
    RecordsReturnFlag = False
    RequiredRowNumber = 1
    ParameterTotal = -1
   
    'Initialize properties to be populated by this ActiveX object
    ColumnTotal = -1
    RowTotal = -1
    RowInfo = ""
    ErrorString = ""
    MySQLString = ""
    MyConnCleanupFlag = False
    MyRsetCleanupFlag = False
    Exit Sub
End Sub
Public Function Execute()
    On Error GoTo ErrorLabel
    ErrorString = "In Execute"
    If PrepareSQLString <> 0 Then
        GoTo ErrorLabel
    End If
   
    If (RecordsReturnFlag = False) Then
        If ExecuteSQLWithOutRecords <> 0 Then
            GoTo ErrorLabel
        End If
    Else
        If ExecuteSQLWithRecords <> 0 Then
            GoTo ErrorLabel
        End If
    End If
    Execute = 0
    GoTo ExitLabel
ErrorLabel:
    Execute = -1
ExitLabel:
    Exit Function
End Function

Private Function PrepareSQLString()
    'this function substitues the parameters in SQLString
    'as required
    Dim LoopIndex As Integer
    Dim CurrentLocation As Integer
    Dim NextLocation As Integer
    Dim ParmType As String
    Dim ParmValue As String
   
    On Error GoTo UnknownErrorLabel
    MySQLString = SQLString
   
    'check for parameters
    If ParameterTotal = 0 Then
        PrepareSQLString = 0
        GoTo ExitLabel
    ElseIf ParameterTotal < 0 Then
        PrepareSQLString = -1
        ErrorString = "Invalid property set by client: " & _
                     "ParameterTotal = <" & ParameterTotal & ">"
        GoTo ExitLabel
    End If
   
    CurrentLocation = 1
    NextLocation = 0
           
    'substitute parameters in order for each "?" found
    For LoopIndex = 1 To ParameterTotal
        If CurrentLocation > Len(SQLString) Then
            Exit For
        End If
        'check original string for next parameter
        NextLocation = InStr(CurrentLocation, SQLString, "?", vbTextCompare)
        'check if parameter symbol if found
        If NextLocation = 0 Then
            ErrorString = "Incorrect # of parameters specified"
            GoTo ErrorLabel
        End If
        If ParameterType(LoopIndex) = "TEXT" Then
            MySQLString = Replace(MySQLString, "?", "'" & ParameterValue(LoopIndex) & "'", 1, 1, vbTextCompare)
        Else
            MySQLString = Replace(MySQLString, "?", ParameterValue(LoopIndex), 1, 1, vbTextCompare)
        End If
        CurrentLocation = CurrentLocation + 1
        NextLocation = 0
    Next
   
    PrepareSQLString = 0
    GoTo ExitLabel

ErrorLabel:
    PrepareSQLString = -1
    GoTo ExitLabel

UnknownErrorLabel:
    ErrorString = "Error Number<" & Err.Number & _
        "> Error Description = <" & Err.Description & ">"
    PrepareSQLString = -1

ExitLabel:
    Exit Function
End Function
Private Function ExecuteSQLWithOutRecords()

    On Error GoTo ErrorLabel
    Dim ConnString As String
   
    Set MyConn = New ADODB.Connection
    MyConnCleanupFlag = True
    Set MyCommand = New ADODB.Command
   
    'formulate connection string
    ConnString = "DSN=" & DSN & ";uid=" & UserID & ";pwd=" & _
                Password & ";database=" & DbaseName
    MyConn.Open (ConnString)
    MyCommand.ActiveConnection = MyConn
    MyCommand.CommandText = MySQLString
    MyCommand.Execute
   
    ExecuteSQLWithOutRecords = 0
    GoTo ExitLabel
ErrorLabel:
    ErrorString = "Error Number<" & Err.Number & _
        "> Error Description = <" & Err.Description & ">"
    ExecuteSQLWithOutRecords = -1
ExitLabel:
    Exit Function
End Function

Private Function ExecuteSQLWithRecords()

    On Error GoTo UnknownErrorLabel
   
    Dim LoopIndex As Integer
    Dim ConnString As String
    Set MyConn = New ADODB.Connection
    Set MyRset = New ADODB.Recordset
   
    MyConnCleanupFlag = True
    MyRsetCleanupFlag = True
    'formulate connection string
    ConnString = "DSN=" & DSN & ";uid=" & UserID & ";pwd=" & _
                Password & ";database=" & DbaseName
    MyConn.Open (ConnString)
    MyRset.Open MySQLString, MyConn, adOpenStatic, adLockReadOnly, adCmdText

    'populate record count and record info
    If MyRset.BOF And MyRset.EOF Then
        RowTotal = 0
    Else
        RowTotal = MyRset.RecordCount
        ErrorString = "After columntotal"
        ColumnTotal = MyRset.Fields.Count
        'move to required row number
        If RequiredRowNumber > 0 Then
            MyRset.Move RequiredRowNumber - 1
            If MyRset.BOF Or MyRset.EOF Then
                ErrorString = "RequiredRowNumber <" & RequiredRowNumber & "> not valid"
                GoTo ErrorLabel
            End If
        End If
        For LoopIndex = 0 To MyRset.Fields.Count - 1
            If LoopIndex = 0 Then
                RowInfo = MyRset.Fields.Item(LoopIndex)
            Else
                RowInfo = RowInfo & FieldSeperator & MyRset.Fields.Item(LoopIndex)
            End If
        Next LoopIndex
    End If
   
    ExecuteSQLWithRecords = 0
    GoTo ExitLabel
UnknownErrorLabel:
    ErrorString = "Error Number<" & Err.Number & _
        "> Error Description = <" & Err.Description & ">"
ErrorLabel:
    ExecuteSQLWithRecords = -1
ExitLabel:
    Exit Function
End Function

Private Sub Class_Terminate()
    'close connection if open
    If MyConnCleanupFlag = True Then
        If MyConn.State = adStateOpen Then
            MyConn.Close
        End If
    End If
   
    'close recordset if open
    If MyRsetCleanupFlag = True Then
        If MyRset.State = adStateOpen Then
            MyRset.Close
        End If
    End If
End Sub
==========================

I need this to work. Appreciate all the help.

Thanks
Avatar of P1
P1
Flag of United States of America image

Maybe you should cross post to VB Controls, because the problem is not the DB access, but in your Control Object.
Avatar of AnswerTheMan
AnswerTheMan

from a really quick look at it , it seems that MyCONN is being SET NEW and OPENED 2 times without closing it an SET it to NOTHING in between.
Private Function ExecuteSQLWithRecords()  AND
Private Function ExecuteSQLWithOutRecords() ARE activate each after the other and each one Initializing MyCONN and opens it without closing and destructing in between.
BUT in this case i almost sure that the error msg should be other from the one you get.

   

   
According to the following article, you may need to be using binary compatibility. Have you seen this one?

http://support.microsoft.com/support/kb/articles/Q190/1/31.ASP


Also look at :

http://support.microsoft.com/support/kb/articles/Q193/1/72.ASP

This doesn't seem as on topic for your situation, but I've learned that any little bit of information can sometimes help!
hey, now that i've read your other question i get it.
your dll is initialized and terminate just before you can say Jack Robinson, BECAUSE that's the way you wrote it.
when you call the EXECUTE function from your client the dll is already GONE and OFF.
put in it INITAILIZE method some invisible FORM to keep the DLL ALIVE  - so your client will have it avail;able.
Avatar of kkandasa

ASKER

Hi,
Thank you for the response. I do have some questions.
I read up on "Visual Basic Component shutdown rules" for
an in-process component.

Rules for shutdown:

1) There are no references - internal or external - to
the component's public objects.
In my client sample code, I thought the following statement
ensures reference.
--------
    Dim MySQL As PulseDbase.pDirectSQL
    Set MySQL = New PulseDbase.pDirectSQL
--------

2) The component has no forms visible.
I have no forms in my case. You suggested invisible forms. Does that work?

I will try these out. Any comments you have would be
great.

Shouldn't
I think you're right kkandasa, as long as there are references the component
will not unload. And there is a reference as long as your MySQL variable is
valid.

Your code ran without errors on my machine with VB6(SP3). Which VB Version
do you use?

One thing you could try out is the following:
Specify the return type of method execute as:
Public Function Execute() As Boolean
or as
Public Function Execute() As Long

your current Execute returns a variant. Maybe this will help.

>deploying it in other computers seems to be complicated.
If you have many 'trial' instalations, you use trick with CreateObject. See article:
Binary compatibility issues in Visual Basic (Francesco Balena)
http://www.comdeveloper.com/articles/binarycomp.asp
I notice you ar using DSNs. Did you create them on the Client Computer?

I would set the ActiveX dll to binary compatability.
You did not mention if you re-compiled the test program after you compiled the ActiveX dll. With No Compatibility set, a new object ID is generated every time you compile the ActiveX dll. If the test application is not recompiled, the app will be looking for the old object ID that will no longer exist in the registry.

I had to create a package and deploy it. The client
computer did not have SP3 for vb6.

Thanks.
I understand that for you to use DSNs they need to be created on the system that is using them to make Data Connections.
Are your problems solved now?
Yes, the client did not have sp3 for vb6. I created a
package via the package and deployment wizard. It works
now.

Thanks
For this was definitely not a 600 pts question i think it would not be fair to
send an answer. I suggest you ask customer service to delete it.

ask another question with a score you think that is adequate and i'll tell you
another minor bug in your dll code.

Hi Ferkel,
Points is not a problem. I spent over two days
on this problem. Answer this question with the dll
bug you found and I will accept the answer and credit
you with the points.

Thanks.
ASKER CERTIFIED SOLUTION
Avatar of ferkel
ferkel
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks
This question was awarded, but never cleared due to the JSP-500 errors of that time.  It was "stuck" against userID -1 versus the intended expert whom you awarded.  This corrects the problem and the expert will now receive these points; points verified.

Please click on your Member Profile and select "View Question History" to navigate through any open or locked questions you may have to update and finalize them.

This is the Community Support link, if help is needed, along with the link to All Topics since many new ones were recently added.

https://www.experts-exchange.com/jsp/qList.jsp?ta=commspt
https://www.experts-exchange.com/jsp/zonesAll.jsp
 
Thanks,
Moondancer
Moderator @ Experts Exchange