About this chapter
This chapter explains how to build a PowerBuilder client that accesses a COM or COM+ server component.
A PowerBuilder application can act as a client to a COM server. The server can be built using any COM-compliant application development tool and it can run locally, on a remote computer as an in-process server, or in COM+.
Configuring a client computer to access a remote component
When a COM component is running on a remote computer, the client computer needs to be able to access its methods transparently. To do this, the client needs a local proxy DLL for the server and it needs registry entries that identify the remote server.
If the component is installed in COM+, the COM+ Component Services tool can create a Microsoft Windows Installer (MSI) file that installs an application proxy on the client computer.
If the server is not installed in COM+, the client and proxy files must be copied to the client and the server must be configured to run in a surrogate process.
Remote server name written to registry
If the COM server is moved to a different computer, the registry entries on the client must be updated.
To access a method associated with a component in the COM server, the PowerBuilder client connects to the component using its programmatic identifier (ProgID) or its class identifier (CLSID).
You can use a tool such as OLEVIEW or the OLE tab in the PowerBuilder Browser to view the Program ID or CLSID and methods of registered COM objects.
To establish a connection to the COM server, you need to execute the PowerScript statements required to perform these operations:
-
Declare a variable of type OLEObject and use the Create statement to instantiate it.
-
Connect to the object using its Program ID or CLSID.
-
Check that the connection was established.
Example
The following script instantiates the EmpObj OLEObject object, connects to the COM object PBcom.Employee, and checks for errors:
OLEObject EmpObj Integer li_rc EmpObj = CREATE OLEObject li_rc = EmpObj.ConnectToNewObject("PBcom.employee") IF li_rc < 0 THEN DESTROY EmpObj MessageBox("Connecting to COM Object Failed", & "Error: " + String(li_rc)) Return END IF
Invoking component methods
Once a connection to a COM component has been established, the client application can begin using the component methods.
Use the REF keyword for output parameters
You must use the REF keyword when you call a method on a COM object that has an output parameter. For example: of_add( arg1, arg2, REF sum )
Example
Using the EmpObj object created in the previous example, this example calls two methods on the component, then disconnects and destroys the instance:
Long units, time Double avg, ld_retn String ls_retn ld_retn = EmpObj.f_calcdayavg(units, time, REF avg) ls_retn = EmpObj.f_teststring() EmpObj.DisconnectObject() DESTROY EmpObj
Passing result sets
PowerBuilder provides three system objects to handle getting result sets from components running in transaction server environments and returning result sets from PowerBuilder user objects running as transaction server components. These system objects (ResultSet, ResultSets, and ADOResultSet) are designed to simplify the conversion of transaction server result sets to and from DataStore objects and do not contain any state information.
Handling runtime errors
Runtime error information from custom class user objects executing as OLE automation objects, COM objects, or COM+ components is reported to the container holding the object as exceptions (or, for automation objects, as exceptions or facility errors). Calls to the PowerBuilder SignalError function are also reported to the container. To handle runtime errors generated by PowerBuilder objects, code the ExternalException event of the OLE client.
For more information about handling runtime errors in OLE or COM objects, see Handling errors.
PowerBuilder clients can exercise explicit control of a transaction on a COM+ server by using a variable of type OleTxnObject instead of OLEObject to connect to the COM object.
Requires COM+ installation
The ConnectToNewObject call on an OleTxnObject fails if COM+ is not installed on the client computer.
The OleTxnObject object, derived from the OLEObject object, provides two additional functions (SetComplete and SetAbort) that enable the client to participate in transaction control. When the client calls SetComplete, the transaction is committed if no other participant in the transaction has called SetAbort or otherwise failed. If the client calls SetAbort, the transaction is always aborted.
Example
In this example, the clicked event on a button creates a variable of type OleTxnObject, connects to a COM object on a server, and calls some methods on the object. When all the methods have returned, the client calls SetComplete and disconnects from the object.
integer li_rc OleTxnObject lotxn_obj lotxn_obj = CREATE OleTxnObject li_rc = lotxn_obj.ConnectToNewObject("pbcom.n_test") IF li_rc <> 0 THEN Messagebox( "Connect Error", string(li_rc) ) HALT END IF lotxn_obj.f_dowork() lotxn_obj.f_domorework() lotxn_obj.SetComplete() lotxn_obj.DisconnectObject()
This f_dowork function on the COM object on the server creates an instance of the transaction context service and calls its DisableCommit method to prevent the transaction from committing prematurely between method calls. After completing some work, the function calls SetAbort if the work was not successfully completed and SetComplete if it was.
TransactionServer txninfo_one integer li_rc li_rc = GetContextService( "TransactionServer", & txninfo_one ) txninfo_one.DisableCommit() // do some work and return a return code IF li_rc <> 0 THEN txninfo_one.SetAbort() return -1 ELSE txninfo_one.SetComplete() return 1 END IF
The SetComplete call on the client commits the transaction if all of the methods in the transaction called SetComplete or EnableCommit.