Register    Login
 
Professional OPC Development Tools
And Services
 
 
SupportOnline Forums
 
Links: Related Pages
 
Links: Related Services
 
Links: Related Support
 
Links: Related Resources
 
Online Forums

Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see link in upper right corner) in order to Post questions. You do not have to be a licensed user.

OPC Labs team is actively monitoring the forums, and provides answers as soon as possible. For your convenience, we have also assembled a Frequently Asked Questions page.

Please do not use the Contact page for technical support.

HINT: You may use the Search feature (magnifier icon below) in the forums to locate the information you need. You can also search our entire Web site (the search box in the upper right corner of every page).

 
 
SupportSupportKnowledge Base ...Knowledge Base ...QuickOPC-ClassicQuickOPC-ClassicQuickOPC-COMQuickOPC-COMQOC-KB-2. How to dump OPC serverQOC-KB-2. How to dump OPC server's address space recursively to the console in C++
Previous Previous
 
Next Next
New Post
 3/22/2010 3:52 AM
 
 Modified By OPC Labs Webmaster  on 3/22/2010 4:55:25 PM

Following C++ code dumps all branches in leaves in OPC server's address space to the console, with the use of QuickOPC-COM. It has been tested in Visual Studio 2008. Note that the code does not use any MFC or ATL.

// Dumps OPC server's address space recursively to the console.
//
#include "stdafx.h"

#import "libid:FAB7A1E3-3B79-4292-9C3A-DF39A6F65EC1" version(5.0) // EasyOpcDALib
#import "scrrun.dll" rename("DeleteFile", "DeleteFileX") rename("MoveFile", "MoveFileX") rename("CopyFile", "CopyFileX") \
    exclude("IDrive", "IDriveCollection", "IFileSystem", "IFileSystem3", "IFolder", "ITextStream", "IFolderCollection", "IFile", \
    "IFileCollection")

using namespace EasyOpcDALib;
using namespace Scripting;

//

void DumpBranch(IEasyDAClientPtr EasyDAClientPtr, LPCTSTR ParentItemId, int Level)
{
    // Browse all nodes (branches and leaves) under ParentItemId
    IDictionaryPtr NodeElementDictionaryPtr(EasyDAClientPtr->BrowseNodes(_T(""), _T("OPCLabs.KitServer.2"), ParentItemId));
    variant_t vKeys(NodeElementDictionaryPtr->Keys());
    variant_t vItems(NodeElementDictionaryPtr->Items());

    LONG Ubound;
    SafeArrayGetUBound(vKeys.parray, 1, &Ubound);
    for (LONG i = 0; i <= Ubound; i++)
    {
        _variant_t vKey;
        SafeArrayGetElement(vKeys.parray, &i, &vKey);
        _variant_t vItem;
        SafeArrayGetElement(vItems.parray, &i, &vItem);
        IDANodeElementPtr NodeElementPtr(vItem);

        for (int j = 0; j < Level; j++) _tprintf(_T("    "));
        _tprintf(_T("%s: HasChildren %d, IsBranch %d, IsLeaf %d, ItemId '%s', Name '%s'\n"),
            (TCHAR*)_bstr_t(vKey),
            NodeElementPtr->HasChildren,
            NodeElementPtr->IsBranch,
            NodeElementPtr->IsLeaf,
            (TCHAR*)NodeElementPtr->ItemId,
            (TCHAR*)NodeElementPtr->Name);

        // If this node is a branch, dump its children recursively
        if (NodeElementPtr->IsBranch)
            DumpBranch(EasyDAClientPtr, NodeElementPtr->ItemId, Level + 1);
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    // Initialize the COM library
    CoInitialize(NULL);

    // Instatiate the EasyOPC-DA client object
    IEasyDAClientPtr EasyDAClientPtr(__uuidof(EasyDAClient));
    // Dump the OPC address space from the root branch
    DumpBranch(EasyDAClientPtr, _T(""), 0);

    CoUninitialize();

    TCHAR line[80];
    _putts(_T("Press Enter to continue..."));
    _fgetts(line, sizeof(line), stdin);
    return 0;
}

This example has been added to QuickOPC-COM Bonus pack and will be available with its next build.

The output is indented according to the hierarchical structure of the address space. Here is how the actual output may look like:

Demo: HasChildren -1, IsBranch -1, IsLeaf 0, ItemId 'Demo', Name 'Demo'
Greenhouse: HasChildren -1, IsBranch -1, IsLeaf 0, ItemId 'Greenhouse', Name 'Greenhouse'
    Sprinklers: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Greenhouse.Sprinklers', Name 'Sprinklers'
    Temperature: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Greenhouse.Temperature', Name 'Temperature'
    RoofOpen: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Greenhouse.RoofOpen', Name 'RoofOpen'
    Humidity: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Greenhouse.Humidity', Name 'Humidity'
$ServerControl: HasChildren -1, IsBranch -1, IsLeaf 0, ItemId '$ServerControl', Name '$ServerControl'
    $Mode: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId '$ServerControl.$Mode', Name '$Mode'
    Command: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId '$ServerControl.Command', Name 'Command'
Trends: HasChildren -1, IsBranch -1, IsLeaf 0, ItemId 'Trends', Name 'Trends'
    Ramp (1 s): HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Trends.Ramp (1 s)', Name 'Ramp (1 s)'
    Sine (10 s): HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Trends.Sine (10 s)', Name 'Sine (10 s)'
    Ramp (10 s): HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Trends.Ramp (10 s)', Name 'Ramp (10 s)'
    Sine (1 s): HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Trends.Sine (1 s)', Name 'Sine (1 s)'
    Ramp (1 min): HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Trends.Ramp (1 min)', Name 'Ramp (1 min)'
    Sine (1 min): HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Trends.Sine (1 min)', Name 'Sine (1 min)'
    Ramp (10 min): HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Trends.Ramp (10 min)', Name 'Ramp (10 min)'
    Sine (10 min): HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Trends.Sine (10 min)', Name 'Sine (10 min)'
Simulation: HasChildren -1, IsBranch -1, IsLeaf 0, ItemId 'Simulation', Name 'Simulation'
    RegisterSet_2: HasChildren -1, IsBranch -1, IsLeaf 0, ItemId 'Simulation.RegisterSet_2', Name 'RegisterSet_2'
        ArrayOfUI2: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.RegisterSet_2.ArrayOfUI2', Name 'ArrayOfUI2'
        I4: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.RegisterSet_2.I4', Name 'I4'
    Register_RECORD: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.Register_RECORD', Name 'Register_RECORD'
    RegisterSet_3: HasChildren -1, IsBranch -1, IsLeaf 0, ItemId 'Simulation.RegisterSet_3', Name 'RegisterSet_3'
        ArrayOfUI2: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.RegisterSet_3.ArrayOfUI2', Name 'ArrayOfUI2'
        I4: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.RegisterSet_3.I4', Name 'I4'
    Register_I4: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.Register_I4', Name 'Register_I4'
    Register_BOOL: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.Register_BOOL', Name 'Register_BOOL'
    Register_UI4: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.Register_UI4', Name 'Register_UI4'
    RegisterSet_4: HasChildren -1, IsBranch -1, IsLeaf 0, ItemId 'Simulation.RegisterSet_4', Name 'RegisterSet_4'
        ArrayOfUI2: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.RegisterSet_4.ArrayOfUI2', Name 'ArrayOfUI2'
        I4: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.RegisterSet_4.I4', Name 'I4'
    Register_ERROR: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.Register_ERROR', Name 'Register_ERROR'
    Register_UINT: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.Register_UINT', Name 'Register_UINT'
    RegisterSet_5: HasChildren -1, IsBranch -1, IsLeaf 0, ItemId 'Simulation.RegisterSet_5', Name 'RegisterSet_5'
        ArrayOfUI2: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.RegisterSet_5.ArrayOfUI2', Name 'ArrayOfUI2'
        I4: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.RegisterSet_5.I4', Name 'I4'
    Register_DISPATCH: HasChildren 0, IsBranch 0, IsLeaf -1, ItemId 'Simulation.Register_DISPATCH', Name 'Register_DISPATCH'
...
New Post
 1/3/2011 7:03 AM
 

The original code above has a bug in that it does not release the interface pointer soon enough; it may therefore crash upon exiting. The fix is to add the following:

// Release all interface pointers BEFORE calling CoUninitialize()
EasyDAClientPtr = NULL;

Future builds of Bonus Pack will contain the updated example already.

Previous Previous
 
Next Next
SupportSupportKnowledge Base ...Knowledge Base ...QuickOPC-ClassicQuickOPC-ClassicQuickOPC-COMQuickOPC-COMQOC-KB-2. How to dump OPC serverQOC-KB-2. How to dump OPC server's address space recursively to the console in C++

 
 
 
 
 

 
 
 
 
Home|Services|Products|Purchase|Downloads|Support|Resources|Company|Contact
Copyright 2007-2012 by OPC Labs Terms Of Use Privacy Statement May 20, 2012