How can vb.NET app pass Object array to COM OPC server expecting Variant array

0

I am using Visual Studio 2012 .NET 4.0 I have been tasked with moving an application from one system to another. Due to some hardcoded sever refences in the original I have been forced to revise some of the source which is probably vb6 (zero comments in the source). Visual Studio 2012 has forced me to make many syntax revisions including changing Variant to Object.
The new code is executing except for an OPC server connection where I can connect, establish an audit log but the .Read fails with a type mismatch error: Error # 13 Type mismatch. (Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH)) As far as I can tell the parameter arrays are consistent with those described in server reference document except that in the document they are typed as “Variant” and Visual Studio 2012 forces then to type “Object”. My best guess is that the mismatch is due to Object vs Variant. The server .dll and .ocx files in my vb Project are from 2006. I don't have access at this time to more recent versions. I have looked some of the MS VB documentation and I think I might need to use Marshall but I'm not quite sure how to implement it. Any tips would be appreciated.

REM -- Reference document example

Dim arrTagParams As Variant
Dim arrTagValue As Variant
Dim arrTagError As Variant
Dim arrTagStatus As Variant
ReDim arrTagParams(3 - 1) As String
arrTagParam(0) = "BCTCN1_WOPCP01\BCC500.PV"
arrTagParam(1) = "BCTCN1_WOPCP01\BCC500.EUDE1"
arrTagParam(2) = "BCTCN1_WOPCP01\BCC500.DESCR"
iRetStatus = mopc.Read(arrTagParams, arrTagValue, arrTagError, arrTagStatus)

REM -- My Code
Dim oOpcServer As CoxYYyOPC
Dim lReturnCode As Long
REM -- Testing establish an audit file
Const strTestYYY_auditfldr As String = "C:\Users\aeKIHill\My Documents\Visual Studio 2012\TestGcRuns\log"
REM -- Arrays for .Read call
Dim asLbTgRefs As Object
Dim aoLbTgVals As Object
Dim alErrors As Object
Dim aStatus As Object
ReDim asLbTgRefs(0 To aiCount - 1)
ReDim aoLbTgVals(0 To aiCount - 1)
ReDim alErrors(0 To aiCount - 1)
ReDim aStatus(0 To aiCount - 1)
Dim icntA As Integer  'Counter
REM -- Build tag reference strings
For icntA = 0 To aiCount - 1
    asLbTgRefs(icntA) = strnode & "\\" & sOpcServerName & "\" & asItemIds(icntA + 1)
    REM -- aoLbTgVals(icntA) = alValues(icntA + 1)
    otLogFile.WriteLine("OPC tag strings  " & Val(icntA) & " " & asLbTgRefs(icntA))
Next
lReturnCode = 0
On Error GoTo AUD_ERR
oOpcServer = CreateObject("CoxYYyOPCLib.CoxYYyOPC")
lReturnCode = oOpcServer.SetAuditFile(strTestYYY_auditfldr, "gc_cycle", 10, 1000)
Call oOpcServer.SetAuditLevel(5)
Call oOpcServer.AuditText(2, "Audit SetUp rtn = " & Val(lReturnCode))
Call oOpcServer.AuditText(2, "Starting to Read")
On Error GoTo CON_ERR                   'RNL 02-02-03
lReturnCode = 0                        'test
Call oOpcServer.AuditText(2, "lReturnCode = oOpcServer.Read(asLbTgRefs, aoLbTgVals, alErrors, aStatus)")
REM -- statement below failes with type misnmatch error
lReturnCode = oOpcServer.Read(asLbTgRefs, aoLbTgVals, alErrors, aStatus)
Call oOpcServer.AuditText(2, "Read completed")

On Error GoTo READ_ERR If lReturnCode <> 1 Then

vb.net
asked on Stack Overflow Jul 23, 2017 by VBnovice

1 Answer

0

A more experienced colleague found the solution. Put the Object arrays in a VariantWrapper before executing the OPC read as shown below. It requires late binding but that is not an issue with this particular application

REM -- Put Object arrays in a Variant wrapper to satisfy legacy code 
asLbTgRefs = New Runtime.InteropServices.VariantWrapper(asLbTgRefs)
aoLbTgVals = New Runtime.InteropServices.VariantWrapper(aoLbTgVals)
alErrors = New Runtime.InteropServices.VariantWrapper(alErrors)
aStatus = New Runtime.InteropServices.VariantWrapper(aStatus)

REM -- Now this line works
lReturnCode = oOpcServer.Read(asLbTgRefs, aoLbTgVals, alErrors, aStatus)
answered on Stack Overflow Aug 6, 2017 by VBnovice

User contributions licensed under CC BY-SA 3.0