Online Forums
Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see links in upper right corner) in order to Post questions. You do not have to be a licensed user of our product.
Please read Rules for forum posts before reporting your issue or asking a question. OPC Labs team is actively monitoring the forums, and replies as soon as possible. Various technical information can also be found in our Knowledge Base. For your convenience, we have also assembled a Frequently Asked Questions page.
Do not use the Contact page for technical issues.
Testing Demo version with Xojo
Best regards
Please Log in or Create an account to join the conversation.
the BrowserServer function without timeout exception is not a big problem.
Now the basic functions I need to manage OPC Client with COM works.
I Have attached a Xojo project where are available read / write functions, browse methods and timeout settings to help Xojo developers.
Best Regards
Sacha
Attachments:
Please Log in or Create an account to join the conversation.
thank you for the details.
I found that BrowseServers indeed does behave this way (not just in Xojo). That is, it does not return an error in case of timeout or other problems, just an empty collection. There are some deep design/implementation reasons for this, but to save you from long talk, yes, it can be considered a bug in QuickOPC. Other methods behave OK in this respect.
Let me know how important for you is to have errors returned "normally" from BrowseServers - or whether you can accept the current behavior.
Best regards
Please Log in or Create an account to join the conversation.
1/5-
the Window1 open Event Handler contains the following code :
'EasyDAClient and IstanceParameters are declared as Window1 property
'OPC Client Object
EasyDAClient = New OleObject ("OPCLabs.EasyOpc.DataAccess.EasyDAClient")
'Istance parameters Object
IstanceParameters = new OleObject ("OPCLabs.EasyOpc.DataAccess.Engine.EasyDAInstanceParameters")
'Timeouts parameters Object
TimeoutClient = new OleObject ("OPCLabs.EasyOpc.DataAccess.Engine.EasyDAClientTimeouts")
'Setting timeout parameters
'ReadItem timeout
TimeoutClient.ReadItem = 1000
'WriteItem timeout
TimeoutClient.WriteItem = 1000
'Browse Access timeout
TimeoutClient.BrowseAccessPaths = 1000
'Browse server timeout
TimeoutClient.BrowseServers = 10000
IstanceParameters.Timeouts = TimeoutClient
EasyDAClient.InstanceParameters = IstanceParameters
2/3- In case of timeout, BrowseServers returns a ServerCollection with 0 elements without timeout exception.
Dim ServerCollection as new OLEObject("OpcLabs.EasyOpc.ServerElementCollection")
ServerCollection = EasyDAClient.BrowseServers("")
msgbox(str(ServerCollection.count)) 'Returns 0
4- With other OPC Client i see only the ModbusOPC server, to load It the program needs 3 - 4 seconds
If you want, I can send you my test software.
Best Regard
Sacha
Please Log in or Create an account to join the conversation.
1. There was no setting of the browse timeout in the code you posted - how comes?
2. In case of timeout, BrowseServers returns an error and not an empty collection. And the error (failed HRESULT) should be transformed to run-time error in Xojo I suppose. Were the errors somehow suppressed, or how is it possible that the execution continued after the itmeout?
3. You have not answered my question about the Count of the returned collection before the transformation.
4. Not clear why the browsing is so slow. That is no normal, for a local browse. Have you used some other OPC client (not based on QuickOPC), and is it also slow?
5. I do not understand "The other timeouts like writeitem / readitem give me a timeout exception.". Is that a new problem you want me to look at:? If so, create a separate forum topic for it (with possible link to this one).
Regards
Please Log in or Create an account to join the conversation.
The missing "as" is a copy / paste error.
I found the problem. The demo application Easy OPC - DA needs 7 - 10 seconds to shows the servers, more than the BrowseServer Timeout value in my application.
Note : The other timeouts like writeitem / readitem give me a timeout exception.
Thanks
PS: Working with COM is so hard
Please Log in or Create an account to join the conversation.
your code works fine for me (except that you are missing "As" on the 2nd line).
Can you please provide some additional info? Thank you.
1. Can you take the Count of the ServerCollection itself (before the conversion)? Is it also 0?
2. When you run the (.NET-based) demo that comes with the product, does it show the servers (it has "Browse servers" button) or also nothing?
3. Have you tried other OPC clients on the same computer, and what were the results?
Best regards
Please Log in or Create an account to join the conversation.
Your solution works great for reading nodes and leaves but for reading servers it doesn't return any value.
I have no compiler errors, the item's count returns 0 but the ServerCollection object is not NIL.
Code:
EasyDAClient = New OleObject ("OPCLabs.EasyOpc.DataAccess.EasyDAClient")
Dim ServerCollection OLEObject
ServerCollection = EasyDAClient.BrowseServers("") 'Epmpty string = Local machine
Dim AutomationUtilities As New OLEObject("OPCLabs.AutomationUtilities")
Dim NodeElementElasticVector As OLEObject
NodeElementElasticVector = AutomationUtilities.CollectionToElasticVector(ServerCollection)
Dim ServersArray() as string
Dim count as Integer
count = NodeElementElasticVector.Count
msgbox(str(count) + " Elements")
Dim i as Integer
Dim NodeArray() as string
For i = 0 To count - 1
Dim ServerElement As OLEObject
ServerElement = NodeElementElasticVector.Item(i)
ServerArray.AddRow(ServerElement.toString)
Next
Thanks for your help, best regards
Sacha
Please Log in or Create an account to join the conversation.
First of all, please understand that we are total Xojo beginners here - we cannot have advanced experience with all the tools and languages our software gets used from. So if I get something wrong, you may know better.
In my original test, I was declaring the enumerator as OLEObject, and GetEnumerator succeeded but the result was nil.
I then found COM.IEnumVARIANT (docs.xojo.com/IEnumVARIANT ), which seems to be precisely for what we need. But declaring the output variable as COM.IEnumVARIANT gives NilObjectException. But I know that GetEnumerator works - other COM tools are using it - otherwise they wouldn't be able to consume this collection.
So at this point I would be lost; don't you have some working example COM.IEnumVARIANT (perhaps with other object), or some other ideas worth exploring?
But, I found a workaround then. Currently, it is a hack, we can improve it later. Here is what works:
I know we have an object in QuickOPC, called ElasticVector, which certainly can be consumed by Xojo. Besides other things, it is a COM collection indexed by an integer, which is what we need. We designed the ElasticVector to get around a different deficiency in other tool (PowerScript).
So what we need is to convert the DANodeElementCollection to ElasticVector. Unfortunately there is no method for that, but I wrote a little component in VBScript which can do it. This is the hackish part: This component needs to be registered on the machine, too. I am attaching the file (AutomationUtilities.wsc, zipped) to this post, and below is the listing.
<?XML version="1.0"?>
<!-- $Header: $ !-->
<!-- Copyright (c) CODE Consulting and Development, s.r.o., Plzen. All rights reserved. !-->
<!-- Automation utilities for various operations. -->
<?component error="false"?>
<component>
<registration
progid="OPCLabs.AutomationUtilities"
classid="{E8601766-CF3E-4D0A-A29C-858883B52ED4}"
description="OPC Labs Automation Utilities"
version="1"
remotable="true">
</registration>
<public>
<method name="CollectionToElasticVector">
<parameter name="Collection"/>
</method>
</public>
<s-cript language="VBScript">
<![CDATA[
Option Explicit
' Converts a collection to an elastic vector.
Function CollectionToElasticVector(Collection)
Dim ElasticVector: Set ElasticVector = CreateObject("OpcLabs.BaseLib.Collections.ElasticVector")
Dim Element: For Each Element in Collection
ElasticVector.Add(Element)
Next
Set CollectionToElasticVector = ElasticVector
End Function
]]>
</script>
</component>
You need to place the AutomationUtilities.wsc file on your machine, and - using elevated privileges (run the command line "As Administrator"), execute
regsvr32 AutomationUtilities.wsc
After that, the following code in Xojo can be used to access elements of DANodeElementCollection:
' Create EasyOPC-DA component
Dim Client As New OleObject ("OpcLabs.EasyOpc.DataAccess.EasyDAClient")
Dim LeafElements As OLEObject
LeafElements = Client.BrowseLeaves("", "OPCLabs.KitServer.2", "Simulation")
Dim AutomationUtilities As New OLEObject("OPCLabs.AutomationUtilities")
Dim leafElementElasticVector As OLEObject
leafElementElasticVector = AutomationUtilities.CollectionToElasticVector(LeafElements)
Dim count as Integer
count = leafElementElasticVector.Count
Dim i as Integer
For i = 0 To count - 1
Dim LeafElement As OLEObject
LeafElement = LeafElementElasticVector.Item(i)
// do something with LeafElement
Next
Ideally, in the future, we would like be able to do this without the external component (I found the need of additional conversion to ElasticVector as acceptable compromise for Xojo, but not the fact that an external component is needed for that). My envisioned solution would be a method (probably "AddRange") on the ElasticVector that would take all elements from any collection and add them to ElasticVector. I want this to become part of next version (QuickOPC 2020.3) if possible.
Best regards
Attachments:
Please Log in or Create an account to join the conversation.
I was able to reproduce the problem. I think it is because the GetEnumerator returns IEnumVARIANT which is not an automation or dual interface, it is a custom interface only. Most COM controllers have some kind of "For Each" statement precisely for this - to consume an enumerator without explicit programming on the developer's side.
And I think it is discussed here: forums.realsoftware.com/viewtopic.php?t=311 .
You might be able to access some collections using their Count and (indexed) Item properties. The DANodeElementCollection has them too, but the Item property is not indexed by an integer - it is a keyed collection, and the Item is indexed by the node name; and you do not know the node name, for that you would need the GetEnumerator.
This seems to be like a deficiency in Xojo - but one unlikely to be fixed/addressed. We are generally trying to provide some way of doing things in the tools we know about (and believe me, each COM API consumer has its own lot of problems, mostly different from the others). So I will think of whether we can find some way to do this for Xojo. I will make a new post here when I have an update (probably later this week).
Best regards
Please Log in or Create an account to join the conversation.