Kbase 19756: How to Get PID and Process Names of Running Processes from 4GL for NT4 and Windows2000?
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  1/11/2008 |
|
Status: Verified
GOAL:
How to retrieve PID's & Process names of running processes from within Progress 4GL code in a Windows environment?
GOAL:
Windows API to retrieve PID of a process
GOAL:
Windows API to retrieve Process name of running processes
FACT(s) (Environment):
Progress 8.X
Progress 9.X
Windows 32 Intel
Windows NT 4.0
Windows 2000
FIX:
This has been tested on Windows NT4 and also Windows 2000 Professional version.
On Windows 95 and Windows 98 you cannot use then psapi.dll (Process Status Helper). There is however an alternative function (toolhelp), which works with Windows 95, 98 & 2000.
Progress Solution 19757 gives an example of this other method.
Code example:
&GLOB PROCESS_QUERY_INFORMATION 1024
&GLOB PROCESS_VM_READ 16
&GLOB MAX_PATH 260
PROCEDURE EnumProcesses EXTERNAL "psapi.dll" :
DEFINE INPUT PARAMETER vPidListProcess AS LONG.
DEFINE INPUT PARAMETER cb AS LONG.
DEFINE OUTPUT PARAMETER cbNeeded AS LONG.
DEFINE RETURN PARAMETER RetVal AS LONG.
END PROCEDURE.
PROCEDURE EnumProcessModules EXTERNAL "psapi.dll" :
DEFINE INPUT PARAMETER hProcess AS LONG.
DEFINE INPUT PARAMETER lphModule AS LONG.
DEFINE INPUT PARAMETER cb AS LONG.
DEFINE OUTPUT PARAMETER cbNeeded AS LONG.
DEFINE RETURN PARAMETER RetVal 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 CHAR.
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 RetVal AS LONG.
END PROCEDURE.
FUNCTION GetProcessName RETURNS CHAR (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 vProcessName AS CHAR NO-UNDO.
DEFINE VARIABLE RetVal AS INTEGER NO-UNDO.
RUN OpenProcess ( {&PROCESS_QUERY_INFORMATION} +
{&PROCESS_VM_READ}, 0, PID,
OUTPUT hProcess).
vProcessName = "unknown" + FILL(" ", {&MAX_PATH}).
IF hProcess NE 0 THEN DO:
SET-SIZE (lphMod) = 4.
RUN EnumProcessModules ( hProcess,
GET-POINTER-VALUE(lphMod),
GET-SIZE(lphMod),
OUTPUT cbNeeded,
OUTPUT RetVal).
IF RetVal NE 0 THEN DO:
RUN GetModuleBaseNameA (hProcess,
GET-LONG(lphMod,1),
OUTPUT vProcessName,
LENGTH(vProcessName),
OUTPUT RetVal).
vProcessName = SUBSTRING(vProcessName,1,RetVal).
SET-SIZE (lphMod) = 0.
END.
RUN CloseHandle ( hProcess, OUTPUT RetVal).
END.
RETURN TRIM(vProcessName).
END FUNCTION.
/****************** MAIN BLOCK *******************/
DEFINE VARIABLE vPID AS INTEGER NO-UNDO.
DEFINE VARIABLE vPidList AS MEMPTR NO-UNDO.
DEFINE VARIABLE cbNeeded AS INTEGER NO-UNDO.
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DEFINE VARIABLE vRetVal AS INTEGER NO-UNDO.
DEFINE VARIABLE v-processlist AS CHARACTER NO-UNDO.
SET-SIZE(vPidList) = 1000.
RUN EnumProcesses (INPUT GET-POINTER-VALUE(vPidList),
INPUT GET-SIZE(vPidList),
OUTPUT cbNeeded,
OUTPUT vRetVal).
DO i = 1 TO cbNeeded / 4 :
vPID = GET-LONG(vPidList, 4 * (i - 1) + 1).
/* Build a list of PID's & Process Names for viewing */
v-processlist = v-processlist + "~n" + string(vPID) + " "
+ GetProcessName(vPID).
/* Test for a certain Process Name - Prowin32.exe */
IF GetProcessName(vPID) = "prowin32.exe" THEN
MESSAGE vPid GetProcessName(vPID) VIEW-AS ALERT-BOX.
END.
SET-SIZE(vPidList) = 0.
/* Full List of PID's & Process Names */
MESSAGE v-processlist VIEW-AS ALERT-BOX TITLE "Process Details".