There is a very useful built-in handle available globally in your application and, among other advantages, is one way to identify all running persistent procedures. This is the SESSION handle. The SESSION system handle has many attributes and methods, all of which you can learn about in the ABL Reference. You can also see a list of all SESSION attributes by accessing the Session Attributes tool in Progress Developer Studio for OpenEdge (OpenEdge > General PRO*Tools > Session Settings).

Figure 1. Session Attributes PRO*Tool

Some of these attributes have readable values that are meaningful to you when you look at them as a list. However, handles are not useful just as numbers (such as the FIRST-CHILD handle value, shown in the figure).

Your application, however, can make good use of these handles. If you want to examine a list of all running persistent procedures, you start with the SESSION:FIRST-PROCEDURE attribute. This attribute evaluates to the procedure handle of the first of a list of all running procedures. Note that there is no predictable sequence to the procedures in the list. All you can do is scan the list if you need to search for a procedure you are interested in. From here, you can walk through a sequence of all procedures using the NEXT-SIBLING attribute, which also returns a procedure handle, or with the PREV-SIBLING attribute if you want to walk backwards through the list. The last procedure in the list is available using the LAST-PROCEDURE attribute.

Here’s a very simple example. h-FindUseful.p runs another procedure, h-UsefulProc.p, persistent. Then it searches the session’s procedure list for an internal procedure it wants to run:
/* h-FindUseful.p -- searches for a persistent procedure with a useful
  routine to run. */
VAR HANDLE hUseful.
VAR HANDLE hProc.

RUN h-UsefulProc.p PERSISTENT SET hUseful.

hProc = SESSION:FIRST-PROCEDURE.
DO WHILE VALID-HANDLE(hProc):
  IF LOOKUP ("UsefulRoutine1", hProc:INTERNAL-ENTRIES) NE 0 THEN
    DO:
      RUN UsefulRoutine1 IN hProc.
      LEAVE.
    END.
    hProc = hProc:NEXT-SIBLING.
END.

DELETE PROCEDURE hUseful.
In a more realistic example, of course, the same procedure that started h-UsefulProc.p would not be the one searching for it. h-UsefulProc.p defines some internal procedures that other procedures in the session would like to run:
/* h-UsefulProc.p -- has an internal procedure others want to find. */

PROCEDURE UsefulRoutine1:
  MESSAGE "It would be useful if you ran this."
    VIEW-AS ALERT-BOX.
END PROCEDURE.

PROCEDURE UsefulRoutine2:
  MESSAGE "This would be useful too."
    VIEW-AS ALERT-BOX.
END PROCEDURE.
When you run h-FindUseful.p, it locates the running instance of h-UsefulProc.p by looking at every procedure’s INTERNAL-ENTRIES attribute, and runs the routine it is looking for, as shown here: