I am currently using the EnumProcesses function to obtain a list of running processes. Since my application runs in user space, however, it is开发者_开发问答 not able to get handles for processes not running under the user, including System processes. Is there another method that will give me access to these? All I need are the process names.
Just to add to this answer, I built this for cases when you are looking for just one particular process instead of the entire list.
bool FindRunningProcess(AnsiString process) {
/*
Function takes in a string value for the process it is looking for like ST3Monitor.exe
then loops through all of the processes that are currently running on windows.
If the process is found it is running, therefore the function returns true.
*/
AnsiString compare;
bool procRunning = false;
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE) {
procRunning = false;
} else {
pe32.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hProcessSnap, &pe32)) { // Gets first running process
if (pe32.szExeFile == process) {
procRunning = true;
} else {
// loop through all running processes looking for process
while (Process32Next(hProcessSnap, &pe32)) {
// Set to an AnsiString instead of Char[] to make compare easier
compare = pe32.szExeFile;
if (compare == process) {
// if found process is running, set to true and break from loop
procRunning = true;
break;
}
}
}
// clean the snapshot object
CloseHandle(hProcessSnap);
}
}
return procRunning;
}
I should note here this was written in Embarcadero RAD Studio (C++ Builder) and per @Remy_Lebeau System::AnsiString is a C++Builder string class for 8bit ANSI character data in its VCL/FMX frameworks.
I finally found a solution (figures after posting here as my last desperate attempt). If anyone else only needs a list of process names running on the system (all processes), this will do it for you.
Process Walking
If all you need are just process names, then use WTSEnumerateProcesses as such:
WTS_PROCESS_INFO* pWPIs = NULL;
DWORD dwProcCount = 0;
if(WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, NULL, 1, &pWPIs, &dwProcCount))
{
//Go through all processes retrieved
for(DWORD i = 0; i < dwProcCount; i++)
{
//pWPIs[i].pProcessName = process file name only, no path!
//pWPIs[i].ProcessId = process ID
//pWPIs[i].SessionId = session ID, if you need to limit it to the logged in user processes
//pWPIs[i].pUserSid = user SID that started the process
}
}
//Free memory
if(pWPIs)
{
WTSFreeMemory(pWPIs);
pWPIs = NULL;
}
The benefit of using this method is that you don't have to open each process individually and then retrieve its name as what you'd have to do if you went with EnumProcesses instead, which also won't work if you try to open processes that run with higher privileges than your user account.
Additionally this method is also much faster than calling Process32First()
/Process32Next()
in a loop.
WTSEnumerateProcesses
is a lesser known API that has been available since Windows XP.
A WMI query (quite possible using WMI's COM interface, but you'll need to translate VB(Script) focused documentation) might help here. The Win32_Process
class contains what you need.
However, I've not tested this, I think you'll find the same issue: a non-administrator can only see their own processes.
精彩评论