1. Berka Frenfert
  2. PowerBuilder
  3. Wednesday, 15 January 2020 08:55 AM UTC

Challenge: Run PowerScript code stored in a string variable.

Limitation: The only object that can be imported into a library is DataWindow.

Who can do this?

 

Michael Kramer Accepted Answer Pending Moderation
  1. Thursday, 16 January 2020 12:34 PM UTC
  2. PowerBuilder
  3. # 1

Hi Berka, thanks for clarifying details.

UPDATE: Added 4 more "PowerScript dynamic features"
All in all lots of ways to change behavior dynamically.
Only prerequisite: Code must be compiled prior to adding it to running app.

PowerScript is a compiled language, not interpreted unlike JavaScript. Therefore, you don't find Execute( ... ) to dynamically execute strings. ORCA is the technology that actually enables exactly what you are requesting.

Short of ORCA there are several ways to make code "dynamic" in different shapes and sizes:

  • Use PB IDE to alter code after original compile time; then apply modified/new code at runtime.
    • Use SetLibraryList to modify library list at runtime.
      Add libraries and/or change sequence in the library list.
    • Deliver some source code PBL files along with your app.
      Allows users to modify a subset of classes and DataWindow objects.
    • Deliver full app as source code so end-user or third-party can modify everything.

  • Use dynamic linking/late binding of external code - albeit these are not PowerScript
    • Any C# assembly loaded using new C# interop in PB 2019 R2
    • Any COM object referenced via OLEObject
    • Any external function call
    • Any stored procedure or user-defined function

  • User PowerScript dynamic features
    • Call events using TriggerEvent/PostEvent - event name is text.
    • Call methods using DYNAMIC - late binding at runtime. Watch for exceptions.
    • Use Describe( "Evaluate( ... )" ) in DataWindow/DataStore.
    • Create DataWindow objects from scratch - full syntax is text.
    • Use string variable to determine DataWindow object name.
    • Use string variable to determine DataWindow column name.
    • CREATE USING "..." to create any class on demand.
    • Open/OpenWithParm "syntax 2" to open any window class on demand.
    • OpenSheet/OpenSheetWithParm "syntax 2" to open any window class as a sheet on demand.
    • OpenTab/OpenTabWithParm "syntax 2" to open  any tab page on demand.
    • OpenUserObject/OpenUserObjectWithParm "syntax 2" to open any visual user object on demand.

In any case, I must stress using "very dynamic" coding techniques are potential security risks especially when you let user modify code as app is running. How will you do security analysis of code written while app is running?

HTH /Michael

 

Comment
There are no comments made yet.
Roland Smith Accepted Answer Pending Moderation
  1. Wednesday, 15 January 2020 20:56 PM UTC
  2. PowerBuilder
  3. # 2

If you want to use ORCA to import code objects, you are going to need several runtime DLL files that aren't normally part of the application runtime.

Also, because PB doesn't support call back functions, you cannot get any error messages if the import fails.

 

Comment
There are no comments made yet.
mike S Accepted Answer Pending Moderation
  1. Wednesday, 15 January 2020 16:07 PM UTC
  2. PowerBuilder
  3. # 3

see evaluate under the describe notation.

 

also, functions can run from a pbl, so if you do import a function at runtime it would work

 

Comment
There are no comments made yet.
Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Wednesday, 15 January 2020 15:59 PM UTC
  2. PowerBuilder
  3. # 4

Hi Berka;

   First of all you are correct .. the LibraryImport() method only supports DWO's.  :-(

   This command restriction was made by PowerSoft as they wanted to sell the ORCA API for profit. To make this so they crippled the LibraryImport command and then charged extra $$$ for the ORCA API. When Sybase made the ORCA API part of the PB product, they should have removed the LibraryImport command class restriction (IMHO). Then all PB developers could write "kool" utilities for PB! Just my $0.02.

   I have done dynamic code PowerScript code before. However, the PB architecture is based on a "compiled" model vs say VB which is an "Interpretive" execution model. Since the DWO source can be imported at run time and the DWO supports dynamic expressions .. this is the way I have implemented this "dynamic PowerScript" feature in the past.

Food for thought. HTH

Regards ... Chris

 

Comment
There are no comments made yet.
Michael Kramer Accepted Answer Pending Moderation
  1. Wednesday, 15 January 2020 13:19 PM UTC
  2. PowerBuilder
  3. # 5

Berka, a couple of clarifying questions to help me and others better understand what you are looking for.

  • Are you looking for PowerBuilder's equivalent of JavaScript's Evaluate(...)?
  • Do you have sample "PowerScript code" you need to execute?
  • How comes you end up with PowerScript code in a text string?

What you are looking for may have severe security implications so I'm hesitant to just throw final answers at you without understanding your context.

Kindly, /Michael
NOTE: Object types beyond DataWindow can be imported via the ORCA API.

Comment
  1. Berka Frenfert
  2. Thursday, 16 January 2020 08:42 AM UTC
ORCA is good but not a plus point for PB because ORCA is another headache.
  1. Helpful
  1. Chris Pollach @Appeon
  2. Thursday, 16 January 2020 16:56 PM UTC
FWIW: That is what OpenUserObject() command is for . For example (from my framework) ...



Message.StringParm = "OPEN USEROBJECT" // Indicate its a User Object

IF Right ( Lower(as_object_name) ,6 ) <> "master" THEN // Base name?

ls_name = as_object_name + "_" + go_ac.of_get_language ( ) // NO=>Compute UO 2 open

END IF

li_rc = ao_window_ptr.OpenUserObject ( ao_dragobject_ptr, ls_name , &

ai_x_position, ai_y_position ) // Instantiate UO!
  1. Helpful
  1. Chris Pollach @Appeon
  2. Thursday, 16 January 2020 16:59 PM UTC
Part II ... You can then use PopulateError to get the UO that was instantianed by the dynamic OpenUserObject ...



IF go_ac.of_is_debug_mode( ) = TRUE THEN // Debug Mode?

IF go_ac.of_get_client_type( ) = "PB" THEN

PopulateError (0, "Open UserObject - global function" ) // Get object info

END IF

lo_sr.si_data [ 1 ] = ls_name // Load UO name

lo_sr.si_data [ 2 ] = String (li_rc) // Load RC

lo_sr.si_data [ 3 ] = "fn_open_user_object" // Load Function Name

go_ac.of_get_message (71, ls_title, ls_msg, lo_sr) // Get MSG

go_ac.of_write_log (ls_msg) // Write 2 Log!

END IF



  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.