The process status application programming interface (PSAPI) is a helper library that makes it easier for you to obtain information about processes and device drivers.
These functions are available in Psapi.dll.
The same information is generally available through the performance data in the registry.
The process status API (PSAPI) provides sets of functions for retrieving the following information:
Process Information
Module Information
Device Driver Information
Process Memory Usage Information
Working Set Information
Memory-Mapped File Information
The following sample code uses the EnumProcesses function to enumerate the current processes in the system.
' ========================================================================================
' Enumerating all processes.
' This is a translation of an example included in the MSDN documentation for PSAPI.
' ========================================================================================
' SED_PBCC - Use the PBCC compiler
#COMPILE EXE
#DIM ALL
#INCLUDE "PSAPI.INC"
' ========================================================================================
' Displays the processes
' ========================================================================================
SUB PrintProcessNameAndID (BYVAL processID AS DWORD)
LOCAL szProcessName AS ASCIIZ * %MAX_PATH
LOCAL hProcess AS DWORD
LOCAL hMod AS DWORD
LOCAL cbNeeded AS DWORD
szProcessName = "unknown"
'// Get a handle to the process.
hProcess = OpenProcess(%PROCESS_QUERY_INFORMATION OR _
%PROCESS_VM_READ, %FALSE, processID)
'// Get the process name.
IF ISFALSE hProcess THEN EXIT SUB
IF ISFALSE EnumProcessModules(hProcess, hMod, SIZEOF(hMod), cbNeeded) THEN EXIT SUB
GetModuleBaseName hProcess, hMod, szProcessName, SIZEOF(szProcessName)
'// Print the process name and identifier.
PRINT "Process ID: ", szProcessName, processID
CloseHandle hProcess
END SUB
' ========================================================================================
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
'// Get the list of process identifiers.
DIM aProcesses(0 TO 1023) AS DWORD
LOCAL cbNeeded AS DWORD
LOCAL cProcesses AS DWORD
LOCAL i AS DWORD
IF ISFALSE EnumProcesses(aProcesses(LBOUND(aProcesses)), _
(UBOUND(aProcesses) - LBOUND(aProcesses) + 1) * 4, cbNeeded) THEN EXIT FUNCTION
'// Calculate how many process identifiers were returned.
cProcesses = cbNeeded \ 4
'// Print the name and process identifier for each process.
FOR i = 0 TO cProcesses - 1
PrintProcessNameAndId aProcesses(i)
NEXT
WAITKEY$
END FUNCTION
' ========================================================================================
To determine which processes have loaded a particular DLL, you must enumerate the modules for each process. The following sample code uses the EnumProcessModules function to enumerate the modules of current processes in the system.
' ========================================================================================
' Enumerating all modules for a process.
' This is a translation of an example included in the MSDN documentation for PSAPI.
' ========================================================================================
' SED_PBCC - Use the PBCC compiler
#COMPILE EXE
#DIM ALL
#INCLUDE "PSAPI.INC"
' ========================================================================================
' Displays the modules
' ========================================================================================
SUB PrintModules (BYVAL processID AS DWORD)
DIM hMods(0 TO 1023) AS DWORD
LOCAL hProcess AS DWORD
LOCAL cbNeeded AS DWORD
LOCAL i AS LONG
LOCAL szModName AS ASCIIZ * %MAX_PATH
'// Print the process identifier.
PRINT "Process ID: ", processID
'// Get a list of all the modules in this process.
hProcess = Openprocess (%PROCESS_QUERY_INFORMATION OR _
%PROCESS_VM_READ, %FALSE, processID)
IF hProcess = 0 THEN EXIT SUB
IF ISFALSE EnumProcessModules(hProcess, hMods(LBOUND(hMods)), _
(UBOUND(hMods) - LBOUND(hMods) + 1) * 4, cbNeeded) THEN EXIT SUB
FOR i = 0 TO cbNeeded \ 4
'// Get full path to the module's file
IF GetModuleFileNameEx(hProcess, hMods(i), szModName, SIZEOF(szModName)) THEN
'// Print the module name and handle value.
PRINT szModName, hMods(i)
END IF
NEXT
CloseHandle hProcess
END SUB
' ========================================================================================
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
DIM aProcesses(1024) AS DWORD
LOCAL cbNeeded AS DWORD
LOCAL cProcesses AS DWORD
LOCAL i AS LONG
IF ISFALSE EnumProcesses(aProcesses(LBOUND(aProcesses)), _
(UBOUND(aProcesses) - LBOUND(aProcesses) + 1) * 4, cbNeeded) THEN EXIT FUNCTION
'// Calculate how many process identifiers were returned.
cProcesses = cbNeeded \ 4
'// Print the name of the module for each process.
FOR i = 0 TO cProcesses - 1
PrintModules aProcesses(i)
NEXT
WAITKEY$
END FUNCTION
' ========================================================================================
The following sample code uses the EnumDeviceDrivers function to enumerate the current device drivers in the system. It passes the load addresses retrieved from this function call to the GetDeviceDriverBaseName function to retrieve a name that can be displayed.
' ========================================================================================
' Enumerating all device drivers.
' The main function obtains a list of load addresses by using the EnumDeviceDrivers
' function. For each address, main calls the PrintDeviceDriverbaseName function passing
' to it the driver address.
' ========================================================================================
' SED_PBCC - Use the PBCC compiler
#COMPILE EXE
#DIM ALL
#INCLUDE "PSAPI.INC"
' ========================================================================================
' Displays the device driver address and base name
' ========================================================================================
SUB PrintDeviceDriverBaseName (BYVAL dwImageBase AS DWORD)
LOCAL szBaseName AS ASCIIZ * %MAX_PATH
PRINT "Driver address: ", dwImageBase;
GetDeviceDriverBaseName dwImageBase, szBaseName, SIZEOF(szBaseName)
PRINT szBaseName
END SUB
' ========================================================================================
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
DIM aDrivers(0 TO 1023) AS DWORD
LOCAL cbNeeded AS DWORD
LOCAL cAddresses AS DWORD
LOCAL i AS LONG
'// Get the list of device drivers addresses
IF ISFALSE EnumDeviceDrivers(aDrivers(LBOUND(aDrivers)), _
(UBOUND(aDrivers) - LBOUND(adrivers) + 1) * 4, cbNeeded) THEN EXIT FUNCTION
'// Calculate how many addresses were returned
cAddresses = cbNeeded \ 4
'// Print the base names of the drivers
FOR i = 0 TO cAddresses - 1
PrintDeviceDriverBaseName aDrivers(i)
NEXT
WAITKEY$
END FUNCTION
' ========================================================================================
The following sample code uses the EnumDeviceDrivers function to enumerate the current device drivers in the system. It passes the load addresses retrieved from this function call to the GetDeviceDriverFileName function to retrieve a name that can be displayed.
' ========================================================================================
' Enumerating all device drivers.
' The main function obtains a list of load addresses by using the EnumDeviceDrivers
' function. For each address, main calls the PrintDeviceDriverFileName function passing
' to it the driver address.
' ========================================================================================
' SED_PBCC - Use the PBCC compiler
#COMPILE EXE
#DIM ALL
#INCLUDE "PSAPI.INC"
' ========================================================================================
' Displays the device driver file name
' ========================================================================================
SUB PrintDeviceDriverFileName (BYVAL dwImageBase AS DWORD)
LOCAL szFileName AS ASCIIZ * %MAX_PATH
PRINT "Driver address: ", dwImageBase;
GetDeviceDriverFileName dwImageBase, szFileName, SIZEOF(szFileName)
PRINT szFileName
END SUB
' ========================================================================================
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
DIM aDrivers(0 TO 1023) AS DWORD
LOCAL cbNeeded AS DWORD
LOCAL cAddresses AS DWORD
LOCAL i AS LONG
'// Get the list of device drivers addresses
IF ISFALSE EnumDeviceDrivers(aDrivers(LBOUND(aDrivers)), _
(UBOUND(aDrivers) - LBOUND(adrivers) + 1) * 4, cbNeeded) THEN EXIT FUNCTION
'// Calculate how many addresses were returned
cAddresses = cbNeeded \ 4
'// Print the base names of the drivers
FOR i = 0 TO cAddresses - 1
PrintDeviceDriverFileName aDrivers(i)
NEXT
WAITKEY$
END FUNCTION
' ========================================================================================
To determine the efficiency of your application, you may want to examine its memory usage. The following sample code uses the GetProcessMemoryInfo function to obtain information about the memory usage of a process.
' ========================================================================================
' Collecting memory usage information for a process.
' This is a translation of an example included in the MSDN documentation for PSAPI.
' ========================================================================================
' SED_PBCC - Use the PBCC compiler
#COMPILE EXE
#DIM ALL
#INCLUDE "PSAPI.INC"
' ========================================================================================
' Displays the information
' ========================================================================================
SUB PrintMemoryInfo (BYVAL processID AS DWORD)
LOCAL hProcess AS DWORD
LOCAL pmc AS PROCESS_MEMORY_COUNTERS
'// Print the process identifier
PRINT "Process ID: " processID
'// Print information about the memory usage of the process.
hProcess = Openprocess (%PROCESS_QUERY_INFORMATION OR _
%PROCESS_VM_READ, %FALSE, processID)
IF hProcess = 0 THEN EXIT SUB
IF (GetProcessMemoryInfo(hProcess, pmc, SIZEOF(pmc))) THEN
PRINT "PageFaultCount: ", pmc.PageFaultCount
PRINT "PeakWorkinSetSize: ", pmc.PeakWorkingSetSize
PRINT "WorkingSetSize: "pmc.WorkingSetSize
PRINT "QuotaPeakPagegPoolUsage: ", pmc.QuotaPeakPagedPoolUsage
PRINT "QuotaPagedPoolUsage: ", pmc.QuotaPagedPoolUsage
PRINT "QuotaPeakNonPagedPoolUsage: ", pmc.QuotaPeakNonPagedPoolUsage
PRINT "QuotaNonPagedPoolUsage: ", pmc.QuotaNonPagedPoolUsage
PRINT "PageFileUsage: ", pmc.PageFileUsage
PRINT "PeakPageFileUsage: ", pmc.PeakPageFileUsage
END IF
CloseHandle hProcess
END SUB
' ========================================================================================
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
DIM aProcesses(0 TO 1023) AS DWORD
LOCAL cbNeeded AS DWORD
LOCAL cProcesses AS DWORD
LOCAL i AS LONG
'// Get the list of process identifiers
IF ISFALSE EnumProcesses(aProcesses(LBOUND(aProcesses)), _
(UBOUND(aProcesses) - LBOUND(aProcesses) + 1) * 4, cbNeeded) THEN EXIT FUNCTION
'// Calculate how many process identifiers were returned.
cProcesses = cbNeeded \ 4
'// Print the memory usage for each process
FOR i= 0 TO cProcesses - 1
PrintMemoryInfo aProcesses(i)
NEXT
WAITKEY$
END FUNCTION
' ========================================================================================