1. Konstantin Goldobin
  2. PowerBuilder
  3. Tuesday, 10 August 2021 10:33 AM UTC

Hello,

I was wondering if there is way of hooking up my handlers for events fired by an external (nonvisual) OLE object. That is, after I create an OLEObject and connect using ConnectToNewObject, I'd like to be able to write a script (an event or function) that would be executed when a certain event that is defined in the external OLE object fires. I saw it in VBScript in the form of WScript.CreateObject( "ProgID", "prefix") but do not know how to do the same in PB.

Best regards,
Konstantin

Konstantin Goldobin Accepted Answer Pending Moderation
  1. Friday, 13 August 2021 10:25 AM UTC
  2. PowerBuilder
  3. # 1

To be more specific, I'm using wodFtpDLXCom, a COM object for working with FTP developed by WeOnlyDo. When an FTP server returns an error, e.g. when a client tries to list the content of a nonexistent directory, the object throws an exception that can be successfully caught in PB and handled. The problem is that apparently error handling is implemented by the object differently for FTP and SFTP: for FTP, the specific error code can be queried via the object property LastError and the error text via the ErrorText method, e.g. "40550 - Requested action not taken. File unavailable (e.g. file not found, no access)"; for SFTP, however, these property and method return a generic error "30031 - Server returned an error:" for any error with no further details.

WeOnlyDo support suggested to write a handler for the object's event Done that receives error code and text. I tried it with VBScript and indeed saw "Server returned an error: No such file or folder". Unfortunately, I haven't been able to do the same in PB, and the support do not know PowerBuilder so they cannot help.

The object provides an alternative way of notification (https://www.weonlydo.com/FtpDLX/Help/wodFtpDLX-Fast-notifications-interface.html). Quoting, "wodFtpDLXCom can use fast notification interface instead of firing events. This means that each time wodFtpDLXCom needs to fire an event, it will call your implementation of the event instead." To use this, a custom object that implements the needed interface IwodFtpNotify should be assigned to the Notification property of wodFtpDLXCom. The link provides an example in VB.

This Notification property is shown as having the OLEObject data type in PB IDE object browser, so I created a descendant of OLEObject, declared all procedures that are part of IwodFtpNotify and tried to assign its instance to the Notification property:

iole_child = create n_ole_child
li_res = iole_child.ConnectToNewObject("WeOnlyDo.wodFtpDLXCom.1")
iole_child.Notification = iole_child

This throws a runtime error "Error accessing external object property notification". I also tried to assign a window instance with the same result. The only line that didn't throw a runtime error was:

iole_child.Notification = create n_ole_child

But my implementation of IwodFtpNotify_Done in n_ole_child was never called. I also tried calling SetAutomationPointer:

iole_child.Notification = create n_ole_child
iole_child.Notification.SetAutomationPointer( iole_child)

But this call throws "Null object reference".

So I am wondering how I can assign an object implementing the interface to a property of a COM object that has the OLEObject data type. 

Comment
There are no comments made yet.
Matt Balent Accepted Answer Pending Moderation
  1. Thursday, 12 August 2021 16:32 PM UTC
  2. PowerBuilder
  3. # 2

Not sure if this helps you but I did a couple of blog entries on this (COM based wrappers) based on several Conference sessions.  Here is one link: PowerBuilder – Using C# Visual Objects in PB Classic Applications: Anvil of Time (anvil-of-time.com)

Comment
There are no comments made yet.
Bruce Armstrong Accepted Answer Pending Moderation
  1. Tuesday, 10 August 2021 21:20 PM UTC
  2. PowerBuilder
  3. # 3

If I understand what you want to do, they you need to create your own COM object that is an event sink for the OLE object that you are creating.  I did an article on how to do that using PBNI for the PowerBuilder Developer's Journal (PBDJ) back in 2006 (based on a code sample I did back in 2003).

https://answers.sap.com/questions/10076030/pbni-and-oleobject.html

Unfortunately, in internet terms that's ancient history.  The old PBDJ site is gone, and when I looked up the article on the internet archive (https://archive.org/), it looks like they only ever archived the 2nd page of the article.

You might search around for "pbnioleobject" to see if there is some other reference to the code sample or the article.

Actually Scribd has it, but you have to pay to access it if you're already used up your 30 day free trial.

https://www.scribd.com/document/410320694/in-PowerBuilder-sys-con-com-s-archive-of-magazines-SYS-CON-pdf

 

Comment
  1. Bruce Armstrong
  2. Wednesday, 11 August 2021 14:19 PM UTC
Unfortunately, the discussion in that article gives an overview of the approach, but it doesn't have the code. I've copied the relevant section of the article from the internet archive>



"Nonetheless, there is a mechanism for capturing OLE Automation events (see Figure 4), which is explained in some detail in Microsoft Knowledge Base article 183599. Basically, it's necessary to create another COM object referred to as an "eventsink" that implements the same events as the OLE Automation object you want to capture events from. That eventsink object is then registered with the OLE Automation application's "ConnectionPoint". Now when the OLE Automation object fires an event, that same event fires on the eventsink. Since the eventsink is an object we created, we can have it respond to the event.



We could have implemented this prior to PowerBuilder 9 by creating a separate COM object in PowerBuilder or by writing a custom DLL in C++, either of which would then relay the event notifications on to our PowerBuilder application. However, the introduction of PBNI in PowerBuilder 9 has simplified things for us considerably. Essentially it allows us to create objects in C++ and then use them in PowerBuilder as if they were native PowerBuilder objects. PBNI objects can in fact inherit from PowerBuilder objects, and PowerBuilder can create objects inherited from PBNI objects."



  1. Helpful
There are no comments made yet.
Miguel Leeuwe Accepted Answer Pending Moderation
  1. Tuesday, 10 August 2021 17:24 PM UTC
  2. PowerBuilder
  3. # 4

I've once experimented with a script to activate a window, but I'm not sure how you would have to go about to get an event fired:

 

        integer li_rc
        OleObject ole_wsh
       
        ole_wsh = CREATE OleObject
       li_rc = ole_wsh.ConnectToNewObject ( "WScript.Shell" )
       ole_wsh.AppActivate(as_winTitle)
        Sleep (500)
        ole_wsh.SendKeys (''Hello from PB")

I hope someone else can give better help.

Comment
  1. Konstantin Goldobin
  2. Wednesday, 11 August 2021 10:42 AM UTC
Hello Miguel! Events are fired by the component when something happens. I want to write handlers for those events.
  1. Helpful
  1. Miguel Leeuwe
  2. Thursday, 12 August 2021 08:18 AM UTC
Yes, so ... Bruce's answer is the way to go. (Maybe you can create a .Net assembly and import it using the DLL importer tool. The only problem is see (because I''m a noob), is 'how' to get events defined on the DLL, but it should be possible).
  1. Helpful
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.
We use cookies which are necessary for the proper functioning of our websites. We also use cookies to analyze our traffic, improve your experience and provide social media features. If you continue to use this site, you consent to our use of cookies.