get a list of processes

This procedure can be used to show a list of all running processes, for example to see if Netscape.exe is running. The process indentifier (pid) can be used for getting additional information about the process, or for terminating the process.
This method uses the psapi.dll which only works on NT (and Windows 2000 etc). On Windows 95 or Windows 98 you can not use psapi.dll, instead you can use the much nicer CreateToolhelp32 functions.
To check if you are running Windows NT4.0 see page: which version of Windows is running.

FUNCTION GetProcessName RETURNS CHARACTER (INPUT PID AS INTEGER) :
 
  DEFINE VARIABLE hProcess      AS INTEGER NO-UNDO.
  DEFINE VARIABLE cbNeeded      AS INTEGER NO-UNDO.
  DEFINE VARIABLE lphMod        AS MEMPTR  NO-UNDO.
  DEFINE VARIABLE szProcessName AS CHARACTER    NO-UNDO.
  DEFINE VARIABLE ReturnValue   AS INTEGER NO-UNDO.
 
  /* OpenProcess returns a handle (hProcess),
     needed for querying info about the process */
  RUN OpenProcess ( {&PROCESS_QUERY_INFORMATION} + {&PROCESS_VM_READ},
                    0,
                    PID,
                    OUTPUT hProcess).
 
  /* some system processes can not be queried, 
     like "System" and "System Idle Process" and "csrss.exe".
     ProcessName will be initialized to [unknown] for these processes: */
  szProcessName = "[unknown]" + FILL(" ", {&MAX_PATH}).
  IF hProcess NE 0 THEN DO:
 
     /* EnumProcessModules fills an array of module handles */
     /* The first module handle is a handle to the main module, and that's the 
        only handle you need  */
     SET-SIZE (lphMod) = 4. /* need only one hMod  */
     RUN EnumProcessModules ( hProcess,
                              GET-POINTER-VALUE(lphMod),
                              GET-SIZE(lphMod),
                              OUTPUT cbNeeded,
                              OUTPUT ReturnValue).
     IF ReturnValue NE 0 THEN DO:
        /* GetModuleBaseNameA returns the name of a module.
           Because this module is the main module, it's also considered to 
           be the name of the process */
        RUN GetModuleBaseNameA (hProcess,
                                GET-LONG(lphMod,1),
                                OUTPUT szProcessName,
                                LENGTH(szProcessName),
                                OUTPUT ReturnValue).
        /* ReturnValue is the number of returned bytes (chars): */
        szProcessName = SUBSTRING(szProcessName,1,ReturnValue).
        SET-SIZE (lphMod) = 0.
     END.
     RUN CloseHandle ( hProcess, OUTPUT ReturnValue).
  END.
  RETURN TRIM(szProcessName).
 
END FUNCTION.
 
/* =============== TEST ================ */
 
DEFINE VARIABLE lpId          AS MEMPTR  NO-UNDO.
DEFINE VARIABLE PID           AS INTEGER NO-UNDO.
DEFINE VARIABLE cbNeeded      AS INTEGER NO-UNDO.
DEFINE VARIABLE i             AS INTEGER NO-UNDO.
DEFINE VARIABLE ReturnValue   AS INTEGER NO-UNDO.
 
 
/* lpID is an array of PID's (Process Identifiers) */
SET-SIZE(lpId) = 1000. /* assume room for 250 pid's */
 
/* EnumProcesses fills an array of PID's */
RUN EnumProcesses (INPUT GET-POINTER-VALUE(lpId),
                   INPUT GET-SIZE(lpID),
                   OUTPUT cbNeeded,
                   OUTPUT ReturnValue).
 
DO i = 1 TO cbNeeded / 4 :
  PID = GET-LONG(lpID, 4 * (i - 1) + 1).
 
  /* display what you have found (for testing purposes) */
  MESSAGE 'PID='  PID 
          SKIP
          'Name=' GetProcessName(PID)
           VIEW-AS ALERT-BOX.
END.
 
SET-SIZE(lpId) = 0.

Definitions used in this procedure:

&GLOB PROCESS_QUERY_INFORMATION 1024
&GLOB PROCESS_VM_READ 16
&GLOB MAX_PATH 260
 
PROCEDURE EnumProcesses EXTERNAL "psapi.dll" :
  DEFINE INPUT  PARAMETER lpIdProcess AS LONG.
  DEFINE INPUT  PARAMETER cb          AS LONG.
  DEFINE OUTPUT PARAMETER cbNeeded    AS LONG.
  DEFINE RETURN PARAMETER ReturnValue AS LONG.
END PROCEDURE.
 
PROCEDURE EnumProcessModules EXTERNAL "psapi.dll" :
  DEFINE INPUT  PARAMETER hProcess    AS LONG.
  DEFINE INPUT  PARAMETER lphModule   AS LONG.  /* lp to array of module handles */
  DEFINE INPUT  PARAMETER cb          AS LONG.
  DEFINE OUTPUT PARAMETER cbNeeded    AS LONG.
  DEFINE RETURN PARAMETER ReturnValue AS LONG.
END PROCEDURE.
 
PROCEDURE GetModuleBaseNameA EXTERNAL "psapi.dll" :
  DEFINE INPUT  PARAMETER hProcess      AS LONG.
  DEFINE INPUT  PARAMETER hModule       AS LONG.
  DEFINE OUTPUT PARAMETER lpBaseName    AS CHARACTER.
  DEFINE INPUT  PARAMETER nSize         AS LONG.
  DEFINE RETURN PARAMETER nReturnedSize AS LONG.
END PROCEDURE.
 
PROCEDURE OpenProcess EXTERNAL "kernel32.dll" :
  DEFINE INPUT  PARAMETER dwDesiredAccess AS LONG.
  DEFINE INPUT  PARAMETER bInheritHandle  AS LONG.
  DEFINE INPUT  PARAMETER dwProcessId     AS LONG.
  DEFINE RETURN PARAMETER hProcess        AS LONG.
END PROCEDURE.
 
PROCEDURE CloseHandle EXTERNAL "kernel32.dll" :
  DEFINE INPUT  PARAMETER hObject     AS LONG.
  DEFINE RETURN PARAMETER ReturnValue AS LONG.
END PROCEDURE.