OPC Studio User's Guide and Reference
Examples - OPC Unified Architecture - Call multiple methods

.NET

// This example shows how to call multiple methods, and pass arguments to and
// from them.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using System.Diagnostics;
using OpcLabs.BaseLib.OperationModel;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples._EasyUAClient
{
    class CallMultipleMethods
    {
        public static void Main1()
        {

            UAEndpointDescriptor endpointDescriptor =
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
            // or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            // or "https://opcua.demo-this.com:51212/UA/SampleServer/"
            UANodeDescriptor nodeDescriptor = "nsu=http://test.org/UA/Data/ ;i=10755";

            object[] inputs1 =
            {
                false, 
                1, 
                2, 
                3, 
                4, 
                5, 
                6, 
                7, 
                8, 
                9, 
                10
            };

            TypeCode[] typeCodes1 =
            {
                TypeCode.Boolean,
                TypeCode.SByte,
                TypeCode.Byte,
                TypeCode.Int16,
                TypeCode.UInt16,
                TypeCode.Int32,
                TypeCode.UInt32,
                TypeCode.Int64,
                TypeCode.UInt64,
                TypeCode.Single,
                TypeCode.Double
            };

            object[] inputs2 =
            {
                false, 
                1, 
                2, 
                3, 
                4, 
                5, 
                6, 
                7, 
                8, 
                9, 
                10,
                "eleven"
            };

            TypeCode[] typeCodes2 =
            {
                TypeCode.Boolean,
                TypeCode.SByte,
                TypeCode.Byte,
                TypeCode.Int16,
                TypeCode.UInt16,
                TypeCode.Int32,
                TypeCode.UInt32,
                TypeCode.Int64,
                TypeCode.UInt64,
                TypeCode.Single,
                TypeCode.Double,
                TypeCode.String
            };

            // Instantiate the client object
            var client = new EasyUAClient();

            // Perform the operation.
            ValueArrayResult[] results = client.CallMultipleMethods(new[]
            {
                new UACallArguments(endpointDescriptor, nodeDescriptor, 
                    "nsu=http://test.org/UA/Data/ ;i=10756", inputs1, typeCodes1),
                new UACallArguments(endpointDescriptor, nodeDescriptor, 
                    "nsu=http://test.org/UA/Data/ ;i=10774", inputs2, typeCodes2)
            });

            // Display results
            for (int i = 0; i < results.Length; i++)
            {
                Console.WriteLine();
                Console.WriteLine($"results[{i}]:");

                ValueArrayResult result = results[i];
                if (result.Succeeded)
                {
                    object[] outputs = result.ValueArray;
                    Debug.Assert(outputs != null);

                    for (int j = 0; j < outputs.Length; j++)
                        Console.WriteLine($"    outputs[{j}]: {outputs[j]}");
                }
                else
                    Console.WriteLine($"*** Failure: {result.ErrorMessageBrief}");
            }

            // Example output:
            //results[0]:
            //    outputs[0]: False
            //    outputs[1]: 1
            //    outputs[2]: 2
            //    outputs[3]: 3
            //    outputs[4]: 4
            //    outputs[5]: 5
            //    outputs[6]: 6
            //    outputs[7]: 7
            //    outputs[8]: 8
            //    outputs[9]: 9
            //    outputs[10]: 10

            //results[1]:
            //    outputs[0]: False
            //    outputs[1]: 1
            //    outputs[2]: 2
            //    outputs[3]: 3
            //    outputs[4]: 4
            //    outputs[5]: 5
            //    outputs[6]: 6
            //    outputs[7]: 7
            //    outputs[8]: 8
            //    outputs[9]: 9
            //    outputs[10]: 10
            //    outputs[11]: eleven
        }
    }
}
# This example shows how to call multiple methods, and pass arguments to and
# from them.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in PowerShell on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-PowerShell .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.

#requires -Version 5.1
using namespace OpcLabs.BaseLib.OperationModel
using namespace OpcLabs.EasyOpc.UA
using namespace OpcLabs.EasyOpc.UA.OperationModel

# The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows .
Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUA.dll"
Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUAComponents.dll"

[UAEndpointDescriptor]$endpointDescriptor =
    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
# or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
# or "https://opcua.demo-this.com:51212/UA/SampleServer/"
$nodeDescriptor = New-Object UANodeDescriptor("nsu=http://test.org/UA/Data/ ;i=10755")

$inputs1 = @(
    $false,
    1, 
    2, 
    3, 
    4, 
    5, 
    6, 
    7, 
    8, 
    9, 
    10)

$typeCodes1 = @(
    [TypeCode]::Boolean,
    [TypeCode]::SByte,
    [TypeCode]::Byte,
    [TypeCode]::Int16,
    [TypeCode]::UInt16,
    [TypeCode]::Int32,
    [TypeCode]::UInt32,
    [TypeCode]::Int64,
    [TypeCode]::UInt64,
    [TypeCode]::Single,
    [TypeCode]::Double)


$inputs2 = @(
    $false, 
    1, 
    2, 
    3, 
    4, 
    5, 
    6, 
    7, 
    8, 
    9, 
    10,
    "eleven")

$typeCodes2 = @(
    [TypeCode]::Boolean,
    [TypeCode]::SByte,
    [TypeCode]::Byte,
    [TypeCode]::Int16,
    [TypeCode]::UInt16,
    [TypeCode]::Int32,
    [TypeCode]::UInt32,
    [TypeCode]::Int64,
    [TypeCode]::UInt64,
    [TypeCode]::Single,
    [TypeCode]::Double,
    [TypeCode]::String)

# Instantiate the client object.
$client = New-Object EasyUAClient

# Perform the operation.
$results = $client.CallMultipleMethods(@(
    (New-Object UACallArguments($endpointDescriptor, $nodeDescriptor, 
        "nsu=http://test.org/UA/Data/ ;i=10756", $inputs1, $typeCodes1)),
    (New-Object UACallArguments($endpointDescriptor, $nodeDescriptor, 
        "nsu=http://test.org/UA/Data/ ;i=10774", $inputs2, $typeCodes2))
    ))

# Display results
for ($i = 0; $i -lt $results.Length; $i++) {
    Write-Host
    Write-Host "results[$($i)]:"

    $result = $results[$i]
    if ($result.Succeeded) {
        $outputs = $result.ValueArray
        for ($j = 0; $j -lt $outputs.Length; $j++) {
            Write-Host "    outputs[$($j)]: $($outputs[$j])"
        }
    }
    else {
        Write-Host "*** Failure: $($vtqResult.ErrorMessageBrief)"
    }


# Example output:
#
#results[0]:
#    outputs[0]: False
#    outputs[1]: 1
#    outputs[2]: 2
#    outputs[3]: 3
#    outputs[4]: 4
#    outputs[5]: 5
#    outputs[6]: 6
#    outputs[7]: 7
#    outputs[8]: 8
#    outputs[9]: 9
#    outputs[10]: 10

#results[1]:
#    outputs[0]: False
#    outputs[1]: 1
#    outputs[2]: 2
#    outputs[3]: 3
#    outputs[4]: 4
#    outputs[5]: 5
#    outputs[6]: 6
#    outputs[7]: 7
#    outputs[8]: 8
#    outputs[9]: 9
#    outputs[10]: 10
#    outputs[11]: eleven
}
' This example shows how to call multiple methods, and pass arguments to and
' from them.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.

Imports OpcLabs.BaseLib.OperationModel
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.OperationModel

Namespace _EasyUAClient
    Friend Class CallMultipleMethods
        Public Shared Sub Main1()

            Dim endpointDescriptor As UAEndpointDescriptor =
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
            ' or "http://opcua.demo-this.com:51211/UA/SampleServer" (currently not supported)
            ' or "https://opcua.demo-this.com:51212/UA/SampleServer/"
            Dim nodeDescriptor As UANodeDescriptor = "nsu=http://test.org/UA/Data/ ;i=10755"

            Dim inputs1() As Object =
            { _
                False,
                1,
                2,
                3,
                4,
                5,
                6,
                7,
                8,
                9,
                10
            }

            Dim typeCodes1() As TypeCode =
            { _
                TypeCode.Boolean,
                TypeCode.SByte,
                TypeCode.Byte,
                TypeCode.Int16,
                TypeCode.UInt16,
                TypeCode.Int32,
                TypeCode.UInt32,
                TypeCode.Int64,
                TypeCode.UInt64,
                TypeCode.Single,
                TypeCode.Double
            }

            Dim inputs2() As Object =
            { _
                False,
                1,
                2,
                3,
                4,
                5,
                6,
                7,
                8,
                9,
                10,
                "eleven"
            }

            Dim typeCodes2() As TypeCode =
            { _
                TypeCode.Boolean,
                TypeCode.SByte,
                TypeCode.Byte,
                TypeCode.Int16,
                TypeCode.UInt16,
                TypeCode.Int32,
                TypeCode.UInt32,
                TypeCode.Int64,
                TypeCode.UInt64,
                TypeCode.Single,
                TypeCode.Double,
                TypeCode.String
            }

            ' Instantiate the client object
            Dim client = New EasyUAClient()

            ' Perform the operation
            Dim results() As ValueArrayResult = client.CallMultipleMethods(New UACallArguments() _
    { _
        New UACallArguments(endpointDescriptor, nodeDescriptor, _
            "nsu=http://test.org/UA/Data/ ;i=10756", inputs1, typeCodes1), _
        New UACallArguments(endpointDescriptor, nodeDescriptor, _
            "nsu=http://test.org/UA/Data/ ;i=10774", inputs2, typeCodes2) _
    } _
            )

            ' Display results
            For i As Integer = 0 To results.Length - 1
                Console.WriteLine()
                Console.WriteLine("results[{0}]:", i)

                Dim result As ValueArrayResult = results(i)
                If result.Succeeded Then
                    Dim outputs As Object() = result.ValueArray
                    Debug.Assert(outputs IsNot Nothing)

                    For j As Integer = 0 To outputs.Length - 1
                        Console.WriteLine("    outputs[{0}]: {1}", j, outputs(j))
                    Next j
                Else
                    Console.WriteLine("*** Failure: {0}", result.ErrorMessageBrief)
                End If
            Next i

            ' Example output:
            'outputs[0]: False
            'outputs[1]: 1
            'outputs[2]: 2
            'outputs[3]: 3
            'outputs[4]: 4
            'outputs[5]: 5
            'outputs[6]: 6
            'outputs[7]: 7
            'outputs[8]: 8
            'outputs[9]: 9
            'outputs[10]: 10       

            'results[1]:
            'outputs[0]: False
            'outputs[1]: 1
            'outputs[2]: 2
            'outputs[3]: 3
            'outputs[4]: 4
            'outputs[5]: 5
            'outputs[6]: 6
            'outputs[7]: 7
            'outputs[8]: 8
            'outputs[9]: 9
            'outputs[10]: 10
            'outputs[11]: eleven
        End Sub
    End Class
End Namespace

COM

// This example shows how to call multiple methods, and pass arguments to and from them.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

#include "stdafx.h"    // Includes "QuickOpc.h", and other commonly used files
#include <atlsafe.h>
#include "CallMultipleMethods.h"

namespace _EasyUAClient
{
    void CallMultipleMethods::Main()
    {
        // Initialize the COM library
        CoInitializeEx(NULL, COINIT_MULTITHREADED);
        {
            CComSafeArray<VARIANT> inputs1(11);
            inputs1.SetAt(0, _variant_t(false));
            inputs1.SetAt(1, _variant_t(1));
            inputs1.SetAt(2, _variant_t(2));
            inputs1.SetAt(3, _variant_t(3));
            inputs1.SetAt(4, _variant_t(4));
            inputs1.SetAt(5, _variant_t(5));
            inputs1.SetAt(6, _variant_t(6));
            inputs1.SetAt(7, _variant_t(7));
            inputs1.SetAt(8, _variant_t(8));
            inputs1.SetAt(9, _variant_t(9));
            inputs1.SetAt(10, _variant_t(10));

            CComSafeArray<VARIANT> typeCodes1(11);
            typeCodes1.SetAt(0, _variant_t(TypeCode_Boolean));
            typeCodes1.SetAt(1, _variant_t(TypeCode_SByte));
            typeCodes1.SetAt(2, _variant_t(TypeCode_Byte));
            typeCodes1.SetAt(3, _variant_t(TypeCode_Int16));
            typeCodes1.SetAt(4, _variant_t(TypeCode_UInt16));
            typeCodes1.SetAt(5, _variant_t(TypeCode_Int32));
            typeCodes1.SetAt(6, _variant_t(TypeCode_UInt32));
            typeCodes1.SetAt(7, _variant_t(TypeCode_Int64));
            typeCodes1.SetAt(8, _variant_t(TypeCode_UInt64));
            typeCodes1.SetAt(9, _variant_t(TypeCode_Single));
            typeCodes1.SetAt(10, _variant_t(TypeCode_Double));
            CComVariant vTypeCodes1(typeCodes1);

            _UACallArgumentsPtr CallArguments1Ptr(__uuidof(UACallArguments));
            CallArguments1Ptr->EndpointDescriptor->UrlString = 
                //L"http://opcua.demo-this.com:51211/UA/SampleServer";
                L"opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
                CallArguments1Ptr->NodeDescriptor->NodeId->ExpandedText = L"nsu=http://test.org/UA/Data/ ;i=10755";
            CallArguments1Ptr->MethodNodeDescriptor->NodeId->ExpandedText = L"nsu=http://test.org/UA/Data/ ;i=10756";
            CallArguments1Ptr->InputArguments = inputs1;
            CallArguments1Ptr->InputTypeCodes = vTypeCodes1;

            CComSafeArray<VARIANT> inputs2(12);
            inputs2.SetAt(0, _variant_t(false));
            inputs2.SetAt(1, _variant_t(1));
            inputs2.SetAt(2, _variant_t(2));
            inputs2.SetAt(3, _variant_t(3));
            inputs2.SetAt(4, _variant_t(4));
            inputs2.SetAt(5, _variant_t(5));
            inputs2.SetAt(6, _variant_t(6));
            inputs2.SetAt(7, _variant_t(7));
            inputs2.SetAt(8, _variant_t(8));
            inputs2.SetAt(9, _variant_t(9));
            inputs2.SetAt(10, _variant_t(10));
            inputs2.SetAt(11, _variant_t(L"eleven"));

            CComSafeArray<VARIANT> typeCodes2(12);
            typeCodes2.SetAt(0, _variant_t(TypeCode_Boolean));
            typeCodes2.SetAt(1, _variant_t(TypeCode_SByte));
            typeCodes2.SetAt(2, _variant_t(TypeCode_Byte));
            typeCodes2.SetAt(3, _variant_t(TypeCode_Int16));
            typeCodes2.SetAt(4, _variant_t(TypeCode_UInt16));
            typeCodes2.SetAt(5, _variant_t(TypeCode_Int32));
            typeCodes2.SetAt(6, _variant_t(TypeCode_UInt32));
            typeCodes2.SetAt(7, _variant_t(TypeCode_Int64));
            typeCodes2.SetAt(8, _variant_t(TypeCode_UInt64));
            typeCodes2.SetAt(9, _variant_t(TypeCode_Single));
            typeCodes2.SetAt(10, _variant_t(TypeCode_Double));
            typeCodes2.SetAt(11, _variant_t(TypeCode_String));
            CComVariant vTypeCodes2(typeCodes2);

            _UACallArgumentsPtr CallArguments2Ptr(__uuidof(UACallArguments));
            CallArguments2Ptr->EndpointDescriptor->UrlString = 
                //L"http://opcua.demo-this.com:51211/UA/SampleServer";
                L"opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
            CallArguments2Ptr->NodeDescriptor->NodeId->ExpandedText = L"nsu=http://test.org/UA/Data/ ;i=10755";
            CallArguments2Ptr->MethodNodeDescriptor->NodeId->ExpandedText = L"nsu=http://test.org/UA/Data/ ;i=10774";
            CallArguments2Ptr->InputArguments = inputs2;
            CallArguments2Ptr->InputTypeCodes = vTypeCodes2;

            CComSafeArray<VARIANT> arguments(2);
            arguments.SetAt(0, _variant_t((IDispatch*)CallArguments1Ptr));
            arguments.SetAt(1, _variant_t((IDispatch*)CallArguments2Ptr));
            CComVariant vArguments(arguments);

            // Instantiate the client object
            _EasyUAClientPtr ClientPtr(__uuidof(EasyUAClient));

            // Perform the operation
            CComSafeArray<VARIANT> results;
            results.Attach(ClientPtr->CallMultipleMethods(&vArguments));
    
            // Display results
            for (int i = results.GetLowerBound(); i <= results.GetUpperBound(); i++)
            {
                _tprintf(_T("\n"));
                _tprintf(_T("results(%d):\n"), i);
                _ValueArrayResultPtr ResultPtr = results[i];

                if (ResultPtr->Exception == NULL)
                {
                    CComVariant valueArray(ResultPtr->ValueArray);
                    CComSafeArray<VARIANT> outputs(valueArray.parray);
                    for (int j = outputs.GetLowerBound(); j <= outputs.GetUpperBound(); j++)
                    {
                        _variant_t output(outputs[j]);
                        _variant_t vString;
                        vString.ChangeType(VT_BSTR, &output);
                        _tprintf(_T("    outputs(d)s\n"), i, (LPCTSTR)CW2CT((_bstr_t)vString));
                    }
                }
                else
                    _tprintf(_T("*** Error: %s\n"), (LPCTSTR)CW2CT(ResultPtr->Exception->ToString));
            }
        }
         // Release all interface pointers BEFORE calling CoUninitialize()
        CoUninitialize();
    }
}
// This example shows how to call multiple methods, and pass arguments to and
// from them.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

class procedure CallMultipleMethods.Main;
var
  Arguments: OleVariant;
  CallArguments1, CallArguments2: _UACallArguments;
  Client: EasyUAClient;
  I, J: Cardinal;
  Inputs1, Inputs2: OleVariant;
  Outputs: OleVariant;
  Result: _ValueArrayResult;
  Results: OleVariant;
  TypeCodes1, TypeCodes2: OleVariant;
begin
  Inputs1 := VarArrayCreate([0, 10], varVariant);
  Inputs1[0] := False;
  Inputs1[1] := 1;
  Inputs1[2] := 2;
  Inputs1[3] := 3;
  Inputs1[4] := 4;
  Inputs1[5] := 5;
  Inputs1[6] := 6;
  Inputs1[7] := 7;
  Inputs1[8] := 8;
  Inputs1[9] := 9;
  Inputs1[10] := 10;

  TypeCodes1 := VarArrayCreate([0, 10], varVariant);
  TypeCodes1[0] := TypeCode_Boolean;
  TypeCodes1[1] := TypeCode_SByte;
  TypeCodes1[2] := TypeCode_Byte;
  TypeCodes1[3] := TypeCode_Int16;
  TypeCodes1[4] := TypeCode_UInt16;
  TypeCodes1[5] := TypeCode_Int32;
  TypeCodes1[6] := TypeCode_UInt32;
  TypeCodes1[7] := TypeCode_Int64;
  TypeCodes1[8] := TypeCode_UInt64;
  TypeCodes1[9] := TypeCode_Single;
  TypeCodes1[10] := TypeCode_Double;

  CallArguments1 := CoUACallArguments.Create;
  CallArguments1.EndpointDescriptor.UrlString := 
    //'http://opcua.demo-this.com:51211/UA/SampleServer';
    'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer';
  CallArguments1.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10755';
  CallArguments1.MethodNodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10756';
  CallArguments1.InputArguments := PSafeArray(TVarData(Inputs1).VArray);
  CallArguments1.InputTypeCodes := PSafeArray(TVarData(TypeCodes1).VArray);

  Inputs2 := VarArrayCreate([0, 11], varVariant);
  Inputs2[0] := False;
  Inputs2[1] := 1;
  Inputs2[2] := 2;
  Inputs2[3] := 3;
  Inputs2[4] := 4;
  Inputs2[5] := 5;
  Inputs2[6] := 6;
  Inputs2[7] := 7;
  Inputs2[8] := 8;
  Inputs2[9] := 9;
  Inputs2[10] := 10;
  Inputs2[11] := 'eleven';

  TypeCodes2 := VarArrayCreate([0, 11], varVariant);
  TypeCodes2[0] := TypeCode_Boolean;
  TypeCodes2[1] := TypeCode_SByte;
  TypeCodes2[2] := TypeCode_Byte;
  TypeCodes2[3] := TypeCode_Int16;
  TypeCodes2[4] := TypeCode_UInt16;
  TypeCodes2[5] := TypeCode_Int32;
  TypeCodes2[6] := TypeCode_UInt32;
  TypeCodes2[7] := TypeCode_Int64;
  TypeCodes2[8] := TypeCode_UInt64;
  TypeCodes2[9] := TypeCode_Single;
  TypeCodes2[10] := TypeCode_Double;
  TypeCodes2[11] := TypeCode_String;

  CallArguments2 := CoUACallArguments.Create;
  CallArguments2.EndpointDescriptor.UrlString := 
    //'http://opcua.demo-this.com:51211/UA/SampleServer';
    'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer';
  CallArguments2.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10755';
  CallArguments2.MethodNodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10774';
  CallArguments2.InputArguments := PSafeArray(TVarData(Inputs2).VArray);
  CallArguments2.InputTypeCodes := PSafeArray(TVarData(TypeCodes2).VArray);

  Arguments := VarArrayCreate([0, 1], varVariant);
  Arguments[0] := CallArguments1;
  Arguments[1] := CallArguments2;

  // Instantiate the client object
  Client := CoEasyUAClient.Create;

  // Perform the operation
  TVarData(Results).VType := varArray or varVariant;
  TVarData(Results).VArray := PVarArray(Client.CallMultipleMethods(
    PSafeArray(TVarData(Arguments).VArray)));

  // Display results
  for I := VarArrayLowBound(Results, 1) to VarArrayHighBound(Results, 1) do
  begin
    WriteLn;
    WriteLn('results(', I, '):');
    Result := IInterface(Results[I]) as _ValueArrayResult;

    if Result.Exception = nil then
      begin
        TVarData(Outputs).VType := varArray or varVariant;
        TVarData(Outputs).VArray := PVarArray(Result.ValueArray);
        for J := VarArrayLowBound(Outputs, 1) to VarArrayHighBound(Outputs, 1) do
          try
            WriteLn('    ', 'outputs(', J, '): ', Outputs[J]);
          except
            on EVariantError do WriteLn('*** Error displaying the value');
          end;
      end
    else
      WriteLn('*** Error: ', Result.Exception.ToString);
  end;
end;
// This example shows how to call multiple methods, and pass arguments to and
// from them.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in Object Pascal (Delphi) on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-OP .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

class procedure CallMultipleMethods.Main;
var
  Arguments: OleVariant;
  CallArguments1, CallArguments2: _UACallArguments;
  Client: OpcLabs_EasyOpcUA_TLB._EasyUAClient;
  I, J: Cardinal;
  Inputs1, Inputs2: OleVariant;
  Outputs: OleVariant;
  Result: _ValueArrayResult;
  Results: OleVariant;
  TypeCodes1, TypeCodes2: OleVariant;
begin
  Inputs1 := VarArrayCreate([0, 10], varVariant);
  Inputs1[0] := False;
  Inputs1[1] := 1;
  Inputs1[2] := 2;
  Inputs1[3] := 3;
  Inputs1[4] := 4;
  Inputs1[5] := 5;
  Inputs1[6] := 6;
  Inputs1[7] := 7;
  Inputs1[8] := 8;
  Inputs1[9] := 9;
  Inputs1[10] := 10;

  TypeCodes1 := VarArrayCreate([0, 10], varVariant);
  TypeCodes1[0] := TypeCode_Boolean;
  TypeCodes1[1] := TypeCode_SByte;
  TypeCodes1[2] := TypeCode_Byte;
  TypeCodes1[3] := TypeCode_Int16;
  TypeCodes1[4] := TypeCode_UInt16;
  TypeCodes1[5] := TypeCode_Int32;
  TypeCodes1[6] := TypeCode_UInt32;
  TypeCodes1[7] := TypeCode_Int64;
  TypeCodes1[8] := TypeCode_UInt64;
  TypeCodes1[9] := TypeCode_Single;
  TypeCodes1[10] := TypeCode_Double;

  CallArguments1 := CoUACallArguments.Create;
  CallArguments1.EndpointDescriptor.UrlString := 
    //'http://opcua.demo-this.com:51211/UA/SampleServer';
    //'https://opcua.demo-this.com:51212/UA/SampleServer/';
    'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer';
  CallArguments1.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10755';
  CallArguments1.MethodNodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10756';
  CallArguments1.InputArguments := PSafeArray(TVarData(Inputs1).VArray);
  CallArguments1.InputTypeCodes := TypeCodes1;

  Inputs2 := VarArrayCreate([0, 11], varVariant);
  Inputs2[0] := False;
  Inputs2[1] := 1;
  Inputs2[2] := 2;
  Inputs2[3] := 3;
  Inputs2[4] := 4;
  Inputs2[5] := 5;
  Inputs2[6] := 6;
  Inputs2[7] := 7;
  Inputs2[8] := 8;
  Inputs2[9] := 9;
  Inputs2[10] := 10;
  Inputs2[11] := 'eleven';

  TypeCodes2 := VarArrayCreate([0, 11], varVariant);
  TypeCodes2[0] := TypeCode_Boolean;
  TypeCodes2[1] := TypeCode_SByte;
  TypeCodes2[2] := TypeCode_Byte;
  TypeCodes2[3] := TypeCode_Int16;
  TypeCodes2[4] := TypeCode_UInt16;
  TypeCodes2[5] := TypeCode_Int32;
  TypeCodes2[6] := TypeCode_UInt32;
  TypeCodes2[7] := TypeCode_Int64;
  TypeCodes2[8] := TypeCode_UInt64;
  TypeCodes2[9] := TypeCode_Single;
  TypeCodes2[10] := TypeCode_Double;
  TypeCodes2[11] := TypeCode_String;

  CallArguments2 := CoUACallArguments.Create;
  CallArguments2.EndpointDescriptor.UrlString := 
    //'http://opcua.demo-this.com:51211/UA/SampleServer';
    //'https://opcua.demo-this.com:51212/UA/SampleServer/';
    'opc.tcp://opcua.demo-this.com:51210/UA/SampleServer';
  CallArguments2.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10755';
  CallArguments2.MethodNodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/ ;i=10774';
  CallArguments2.InputArguments := PSafeArray(TVarData(Inputs2).VArray);
  CallArguments2.InputTypeCodes := TypeCodes2;

  Arguments := VarArrayCreate([0, 1], varVariant);
  Arguments[0] := CallArguments1;
  Arguments[1] := CallArguments2;

  // Instantiate the client object
  Client := CoEasyUAClient.Create;

  // Perform the operation
  TVarData(Results).VType := varArray or varVariant;
  TVarData(Results).VArray := PVarArray(Client.CallMultipleMethods(
    Arguments));

  // Display results
  for I := VarArrayLowBound(Results, 1) to VarArrayHighBound(Results, 1) do
  begin
    WriteLn;
    WriteLn('results(', I, '):');
    Result := IInterface(Results[I]) as _ValueArrayResult;

    if Result.Exception = nil then
      begin
        Outputs := Result.ValueArray;
        for J := VarArrayLowBound(Outputs, 1) to VarArrayHighBound(Outputs, 1) do
          WriteLn('    ', 'outputs(', J, '): ', Outputs[J]);
      end
    else
      WriteLn('*** Failure: ', Result.Exception.ToString);
  end;

  VarClear(Results);
  VarClear(TypeCodes2);
  VarClear(TypeCodes1);
  VarClear(Arguments);
end;
REM This example shows how to call multiple methods, and pass arguments to and from them.
REM
REM Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
REM OPC client and subscriber examples in Visual Basic on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VB .
REM Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
REM a commercial license in order to use Online Forums, and we reply to every post.

Public Sub CallMultipleMethods_Main_Command_Click()
    OutputText = ""

    Dim inputs1(10)
    inputs1(0) = False
    inputs1(1) = 1
    inputs1(2) = 2
    inputs1(3) = 3
    inputs1(4) = 4
    inputs1(5) = 5
    inputs1(6) = 6
    inputs1(7) = 7
    inputs1(8) = 8
    inputs1(9) = 9
    inputs1(10) = 10

    Dim typeCodes1(10)
    typeCodes1(0) = 3    ' TypeCode.Boolean
    typeCodes1(1) = 5    ' TypeCode.SByte
    typeCodes1(2) = 6    ' TypeCode.Byte
    typeCodes1(3) = 7    ' TypeCode.Int16
    typeCodes1(4) = 8    ' TypeCode.UInt16
    typeCodes1(5) = 9    ' TypeCode.Int32
    typeCodes1(6) = 10   ' TypeCode.UInt32
    typeCodes1(7) = 11   ' TypeCode.Int64
    typeCodes1(8) = 12   ' TypeCode.UInt64
    typeCodes1(9) = 13   ' TypeCode.Single
    typeCodes1(10) = 14  ' TypeCode.Double

    Dim CallArguments1 As New UACallArguments
    CallArguments1.endpointDescriptor.UrlString = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
    CallArguments1.nodeDescriptor.NodeId.expandedText = "nsu=http://test.org/UA/Data/ ;i=10755"
    CallArguments1.MethodNodeDescriptor.NodeId.expandedText = "nsu=http://test.org/UA/Data/ ;i=10756"
    ' Use SetXXXX methods instead of array-type property setters in Visual Basic 6.0
    CallArguments1.SetInputArguments inputs1
    CallArguments1.SetInputTypeCodes typeCodes1

    Dim inputs2(11)
    inputs2(0) = False
    inputs2(1) = 1
    inputs2(2) = 2
    inputs2(3) = 3
    inputs2(4) = 4
    inputs2(5) = 5
    inputs2(6) = 6
    inputs2(7) = 7
    inputs2(8) = 8
    inputs2(9) = 9
    inputs2(10) = 10
    inputs2(11) = "eleven"

    Dim typeCodes2(11)
    typeCodes2(0) = 3    ' TypeCode.Boolean
    typeCodes2(1) = 5    ' TypeCode.SByte
    typeCodes2(2) = 6    ' TypeCode.Byte
    typeCodes2(3) = 7    ' TypeCode.Int16
    typeCodes2(4) = 8    ' TypeCode.UInt16
    typeCodes2(5) = 9    ' TypeCode.Int32
    typeCodes2(6) = 10   ' TypeCode.UInt32
    typeCodes2(7) = 11   ' TypeCode.Int64
    typeCodes2(8) = 12   ' TypeCode.UInt64
    typeCodes2(9) = 13   ' TypeCode.Single
    typeCodes2(10) = 14  ' TypeCode.Double
    typeCodes2(11) = 18  ' TypeCode.String

    Dim CallArguments2 As New UACallArguments
    CallArguments2.endpointDescriptor.UrlString = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
    CallArguments2.nodeDescriptor.NodeId.expandedText = "nsu=http://test.org/UA/Data/ ;i=10755"
    CallArguments2.MethodNodeDescriptor.NodeId.expandedText = "nsu=http://test.org/UA/Data/ ;i=10774"
    ' Use SetXXXX methods instead of array-type property setters in Visual Basic 6.0
    CallArguments2.SetInputArguments inputs2
    CallArguments2.SetInputTypeCodes typeCodes2

    Dim arguments(1) As Variant
    Set arguments(0) = CallArguments1
    Set arguments(1) = CallArguments2

    ' Instantiate the client object
    Dim Client As New EasyUAClient

    ' Perform the operation
    Dim results As Variant
    results = Client.CallMultipleMethods(arguments)

    ' Display results
    Dim i: For i = LBound(results) To UBound(results)
        OutputText = OutputText & vbCrLf
        OutputText = OutputText & "results(" & i & "):" & vbCrLf
        Dim Result As ValueArrayResult: Set Result = results(i)

        If Result.Exception Is Nothing Then
            Dim outputs As Variant: outputs = Result.ValueArray
            Dim j: For j = LBound(outputs) To UBound(outputs)
                On Error Resume Next
                OutputText = OutputText & Space(4) & "outputs(" & j & "): " & outputs(j) & vbCrLf
                If Err <> 0 Then OutputText = OutputText & Space(4) & "*** Error" & vbCrLf ' occurrs with types not recognized by VB6
                On Error GoTo 0
            Next
        Else
            OutputText = OutputText & "*** Error: " & Result.Exception & vbCrLf
        End If
    Next
End Sub
Rem This example shows how to call multiple methods, and pass arguments to and from them.
Rem
Rem Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
Rem OPC client and subscriber examples in VBScript on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBScript .
Rem Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
Rem a commercial license in order to use Online Forums, and we reply to every post.

Option Explicit

Dim inputs1(10)
inputs1(0) = False
inputs1(1) = 1
inputs1(2) = 2
inputs1(3) = 3
inputs1(4) = 4
inputs1(5) = 5
inputs1(6) = 6
inputs1(7) = 7
inputs1(8) = 8
inputs1(9) = 9
inputs1(10) = 10

Dim typeCodes1(10)
typeCodes1(0) = 3    ' TypeCode.Boolean
typeCodes1(1) = 5    ' TypeCode.SByte
typeCodes1(2) = 6    ' TypeCode.Byte
typeCodes1(3) = 7    ' TypeCode.Int16
typeCodes1(4) = 8    ' TypeCode.UInt16
typeCodes1(5) = 9    ' TypeCode.Int32
typeCodes1(6) = 10   ' TypeCode.UInt32
typeCodes1(7) = 11   ' TypeCode.Int64
typeCodes1(8) = 12   ' TypeCode.UInt64
typeCodes1(9) = 13   ' TypeCode.Single
typeCodes1(10) = 14  ' TypeCode.Double

Dim CallArguments1: Set CallArguments1 = CreateObject("OpcLabs.EasyOpc.UA.OperationModel.UACallArguments")
CallArguments1.EndpointDescriptor.UrlString = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
CallArguments1.NodeDescriptor.NodeId.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10755"
CallArguments1.MethodNodeDescriptor.NodeId.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10756"
CallArguments1.InputArguments = inputs1
CallArguments1.InputTypeCodes = typeCodes1

Dim inputs2(11)
inputs2(0) = False
inputs2(1) = 1
inputs2(2) = 2
inputs2(3) = 3
inputs2(4) = 4
inputs2(5) = 5
inputs2(6) = 6
inputs2(7) = 7
inputs2(8) = 8
inputs2(9) = 9
inputs2(10) = 10
inputs2(11) = "eleven"

Dim typeCodes2(11)
typeCodes2(0) = 3    ' TypeCode.Boolean
typeCodes2(1) = 5    ' TypeCode.SByte
typeCodes2(2) = 6    ' TypeCode.Byte
typeCodes2(3) = 7    ' TypeCode.Int16
typeCodes2(4) = 8    ' TypeCode.UInt16
typeCodes2(5) = 9    ' TypeCode.Int32
typeCodes2(6) = 10   ' TypeCode.UInt32
typeCodes2(7) = 11   ' TypeCode.Int64
typeCodes2(8) = 12   ' TypeCode.UInt64
typeCodes2(9) = 13   ' TypeCode.Single
typeCodes2(10) = 14  ' TypeCode.Double
typeCodes2(11) = 18  ' TypeCode.String

Dim CallArguments2: Set CallArguments2 = CreateObject("OpcLabs.EasyOpc.UA.OperationModel.UACallArguments")
CallArguments2.EndpointDescriptor.UrlString = "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
CallArguments2.NodeDescriptor.NodeId.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10755"
CallArguments2.MethodNodeDescriptor.NodeId.ExpandedText = "nsu=http://test.org/UA/Data/ ;i=10774"
CallArguments2.InputArguments = inputs2
CallArguments2.InputTypeCodes = typeCodes2

Dim arguments(1)
Set arguments(0) = CallArguments1
Set arguments(1) = CallArguments2

' Instantiate the client object
Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.UA.EasyUAClient")

' Perform the operation
Dim results: results = Client.CallMultipleMethods(arguments)

' Display results
Dim i: For i = LBound(results) To UBound(results)
    WScript.Echo
    WScript.Echo "results(" & i & "):"
    Dim Result: Set Result = results(i)

    If Result.Exception Is Nothing Then
        Dim outputs: outputs = Result.ValueArray
        Dim j: For j = LBound(outputs) To UBound(outputs)
            On Error Resume Next
            WScript.Echo Space(4) & "outputs(" & j & "): " & outputs(j)
            If Err <> 0 Then WScript.Echo Space(4) & "*** Error"   ' occurrs with types not recognized by VBScript
            On Error Goto 0
        Next
    Else
        WScript.Echo "*** Error: " & Result.Exception
    End If
Next

Python

# This example shows how to call multiple methods, and pass arguments to and
# from them.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc

# Import .NET namespaces.
from System import *
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.OperationModel import *


endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:51210/UA/SampleServer')
# or 'http://opcua.demo-this.com:51211/UA/SampleServer' (currently not supported)
# or 'https://opcua.demo-this.com:51212/UA/SampleServer/'
nodeDescriptor = UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10755')

#
inputs1 = [False, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
typeCodes1 = [
    TypeCode.Boolean,
    TypeCode.SByte,
    TypeCode.Byte,
    TypeCode.Int16,
    TypeCode.UInt16,
    TypeCode.Int32,
    TypeCode.UInt32,
    TypeCode.Int64,
    TypeCode.UInt64,
    TypeCode.Single,
    TypeCode.Double,
    ]

inputs2 = [False, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 'eleven']
typeCodes2 = [
    TypeCode.Boolean,
    TypeCode.SByte,
    TypeCode.Byte,
    TypeCode.Int16,
    TypeCode.UInt16,
    TypeCode.Int32,
    TypeCode.UInt32,
    TypeCode.Int64,
    TypeCode.UInt64,
    TypeCode.Single,
    TypeCode.Double,
    TypeCode.String,
    ]

# Instantiate the client object.
client = EasyUAClient()

# Perform the operation.
try:
    valueArrayResultArray = client.CallMultipleMethods([
        UACallArguments(endpointDescriptor, nodeDescriptor,
                        UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10756'), inputs1, typeCodes1),
        UACallArguments(endpointDescriptor, nodeDescriptor,
                        UANodeDescriptor('nsu=http://test.org/UA/Data/ ;i=10774'), inputs2, typeCodes2),
        ])
except UAException as uaException:
    print('*** Failure: ' + uaException.GetBaseException().Message)
    exit()

# Display results.
for i, valueArrayResult in enumerate(valueArrayResultArray):
    print()
    print('valueArrayResultArray[', i, ']:', sep='')
    if valueArrayResult.Succeeded:
        assert valueArrayResult.ValueArray is not None
        for j, outputValueArray in enumerate(valueArrayResult.ValueArray):
            print('    valueArray[', j, ']: ', outputValueArray, sep='')
    else:
        print('*** Failure: ', valueArrayResult.ErrorMessageBrief, sep='')

print()
print('Finished.')

 

See Also

Concepts