Why does GetProcessImageFileName return null instead of the address of the process? - c++

I am trying to pool the list of all processes in Qt.For this purpose i am using Windows API.
the following code demonstrates my effort so far:
QList<QString> frmProcess::GetAllRunningProcesses()
{
HANDLE hSysSnapshot = NULL;
HANDLE processHandle;
PROCESSENTRY32 proc;
proc.dwSize = sizeof(proc);
hSysSnapshot = CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS, 0 );
Process32First(hSysSnapshot,&proc);
proc.dwSize = sizeof(proc);
ui->listWidget->clear();
LPWSTR processPath;
list.clear();
do
{
//This block of code is to get each process's path and store it in a list
//PROCESS_ALL_ACCESS is commented out since it fails the program on start-up
processHandle = OpenProcess( /*PROCESS_ALL_ACCESS*/PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, proc.th32ProcessID );
GetProcessImageFileName(processHandle,processPath,MAX_PATH);
procpaths.append(QString::fromWCharArray(processPath));
list.append(QString::fromWCharArray(proc.szExeFile));
} while(Process32Next(hSysSnapshot,&proc));
CloseHandle( hSysSnapshot );
return list;
}
In the code posted above, I am trying to get as much as information i can get on a process, for this i am pooling the process names with the help of CreateToolhelp32Snapshot and then get their path with GetProcessImageFileName. And all of this happen in a timer tick event each milliseconds.
If i run the program , after couple of seconds it crashes, I get segmentation fault.
I also tried debugging since i couldn't get any path relating to any process!
And to my surprise i only get empty strings for path of each process!
What am i doing wrong?

Your GetProcessImageFileName does not receive a proper argument. processPath has to point to valid buffer.
TCHAR processPath[MAX_PATH] = { 0 };
GetProcessImageFileName(processHandle, processPath, _countof(processPath));
Also, you want to check returned value to see if you succeeded or not.

Related

Replacing vector with array or static vector for a better approach

My application runs particular number of processes(different executables) using createprocess(windows api) in parallel(using threads). User can refresh / close my application at any time. As of now, I am pushing the process handles into vector and whenever close request received, I am iterating the vector and terminating(using GetExitCodeProcess and TerminateProcess APIs) and closing(using CloseHandle API) the process handles. Also I am closing the handle of the process when it is completed. The problem with current model is, whenever process completed handle will be closed and when close request received again I will try to close it using vector(handle is not updated). To solve this, I have to update/remove the handle in/from the vector. To do this, need to maintain index.
Since I know the number of process, I want to create a static vector and update it rather than pushing a local object to a vector. Can someone suggest a best approach.
Below is the sample code.
//member object
std::vector<PROCESS_INFORMATION> mProcessHandles;
//this is a thread and will be called multiple times with different executable names in the application
void method(std::string executable)
{
STARTUPINFO startInfo{};
PROCESS_INFORMATION procInfo{};
bool ret = CreateProcess(NULL, executable, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &startInfo, &procInfo);
mProcessInfo.push_back(procInfo);
if(ret)
{
WaitForSingleObject(procInfo.hProcess, INFINITE);
CloseHandle(procInfo.hProcess);
procInfo.hProcess = NULL;
CloseHandle(procInfo.hThread);
procInfo.hThread = NULL;
}
return;
}
//this will be called when application close requested
void forceKill()
{
for (auto &processHandlesIt : mProcessHandles)
{
DWORD errorcode = 0;
GetExitCodeProcess(processHandlesIt.hProcess, &errorcode);
if (errorcode == STILL_ACTIVE)
{
TerminateProcess(processHandlesIt.hProcess, errorcode);
}
CloseHandle(processHandlesIt.hProcess);
processHandlesIt.hProcess = NULL;
CloseHandle(processHandlesIt.hThread);
processHandlesIt.hThread = NULL;
}
}
You should not use handles (in GetExitCodeProcess for example) after they are closed.
I would simply not close those process handles in the threads, and just leave them for the forceKill or other clean-up function to close.
Also, since you are not using procInfo.hThread, you could close it right after CreateProcess returns.
I guess you are not using any other members of the procInfo, so you could only store the process' handles in your vector.

OpenProcess function returns invalid handles

I'm working on an application that creates multiple desktops and gives the user the ability to start whatever applications he desires under the desktop he is currently using.
When that desktop is closed (using a combo key) I want close all applications opened under that desktop. In order to do this I enumarate all processes using the EnumProcesses function and retrive a handle based on every process identifier returned by EnumProcesses using OpenProcess function. Using GetThreadId I retrieve the thread identifier which is used as the parameter for GetThreadDesktop function and the returned handle is compared with the one from my desktop, so I can find out in which desktop the process runs.
At least in theory, this works, because for every process identifier, OpenProcess function returns an invalid handle for GetThreadId (error code 6). I'm running the application as administrator and I enable the SeDebugPrivilege privilege.
I don't understand why the returned handle is always invalid, here is the code that I use:
void iterateProcesses(HDESK threadDesktop)
{
EnableDebugPriv(); // functions enables the SeDebugPrivilege privilege
int found = 0;
int wanted = 0;
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded);
cProcesses = cbNeeded / sizeof(DWORD);
for (i = 0; i < cProcesses; i++)
{
if (aProcesses[i] != 0)
{
found++;
if (GetThreadDesktop(checkProcess(aProcesses[i])) == threadDesktop)
{
wanted++;
}
}
}
}
DWORD checkProcess(DWORD processID)
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, processID);
GetLastError(); // if in the manifest file under 'UAC execution level'
// the application does not requests for administrator rights
// GetLastError() will return code 5 (access denied)
DWORD dwThreadId = GetThreadId(hProcess);
GetLastError(); // return code 6 (ERROR_INVALID_HANDLE)
// dwThreadId returned is always 0 because the handle is not valid
CloseHandle(hProcess);
return dwThreadId;
}
Your error checking is wrong. Please read the documentation again. Only call GetLastError if the function failed.
It's reasonable that you will only be able to get all access to a process handle if you are executing elevated. But you do need to check the value returned by OpenProcess, as described in the documentation. Only proceed if that value indicates success. Otherwise, call GetLastError to find out why.
You are expected to pass a thread handle to GetThreadId. hProcess is a process handle. Hence the ERROR_INVALID_HANDLE error code. But again, you are not checking for errors properly. You must first check the return value, as stated in the documentation. Only if that indicates failure do you call GetLastError.
I'm not sure how you can expect to get a single thread from a process. Processes can, and do, have many threads. Indeed threads can be created and destroyed so perhaps the thread you are looking for is not there anymore. All the same, here's how to enumerate threads in a process: https://msdn.microsoft.com/en-us/library/windows/desktop/ms686852.aspx

How can I wait for an application launched by another application launched by my application Qt/C++

I'm creating a Windows Add/Remove Programs application in Qt 5.4 and I'm becaming crazy to solve a little "puzzle":
My application (APP_0) runs another application (APP_1) and waits for this APP_1 until it terminates.
APP_1 is an uninstaller (i.e. uninstall.exe) and I've not the source code of the APP_1, just of my Qt APP_0.
APP_1, instead of doing the uninstall job, it simply copies itself somewhere in the filesystem (I saw as Au_.exe but other apps could use different names and locations), runs this copy of itself (APP_2) and terminates.
The APP_2 has a GUI and the job I'm waiting for (uninstall) is demanded to the final user of the running APP_2.
In this situation my application (APP_0) stops waiting for APP_1 pratically immediately (because it launches APP_1 and waits for APP_1). But to work properly, obviously, I need to know instead when APP_2 is terminated...
So the question is:
is there a way (using some techniques (hooking?)) to know if and when APP_2 terminates?
Note: Consider that the standard Windows Add/Remove Programs utility does the job successfully (it seems it waits for APP_2). You can test this, for example, installing Adobe Digital Edition. Its uninstaller (uninstall.exe) copies itself into a new folder in the User_Local_Temp folder as Au_.exe, runs it and terminates. But the OS utility successfully waits for Au_.exe and only after it terminates refreshes the list of installed programs.
If this kind of technique (uninstall.exe copies itself somewhere ALWAYS with THE SAME name (Au_.exe) ) the problem could be resolved, obviously, very simply. But I don't think that the name of the copied uninstaller is always the same and also I don't like to assume things I'm not sure are real.
Many thanks in advance
Thanks to IInspectable's suggestion (see his comment... and many thanks guy!) I created a function which solves my problems! I'll share here this function which could be useful to other people with the same (or similar) problem.
For my needs, the function receives as parameter the index of the item to be uninstalled (from a QList) and gets the uninstall string (for example: C:\ProgramFiles\MyApp\uninstall.exe).
Then with this uninstall string, I'll create a process (CreateProcess) and put its handle into a Job Object, so that my function will wait for all the processes ran by this process.
The function itself is pretty simple and can be improved.
Notice that the process MUST be created with the CREATE_BREAKAWAY_FROM_JOB option, otherwise the AssignProcessToJobObject will fail with a "Access Denied" error.
void MainWindow::uniButtonClick(int idx)
{
QMessageBox::StandardButton reply;
QMessageBox::StandardButton err;
reply = QMessageBox::question(this, "Uninstall/Change", "Uninstall " +
ip[idx].displayName +"?\r\n\r\n" + ip[idx].uninstallString,
QMessageBox::Yes|QMessageBox::No);
if (reply == QMessageBox::Yes)
{
//QString s = "C:\\windows\\notepad.exe"; // Just to test Job assignment and createprocess
QString s = ip[idx].uninstallString; // the real uninstaller string
QString jobName = "MyJobObject";
try
{
PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter
STARTUPINFO StartupInfo; //This is an [in] parameter
PJOBOBJECT_BASIC_PROCESS_ID_LIST pList;
HANDLE hProcess;
BOOL bJobAllEnd;
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof StartupInfo ; //Only compulsory field
wchar_t* path;
path = (wchar_t*) malloc (sizeof(wchar_t)*s.length()+1);
s.toWCharArray(path);
path[s.length()]=0; // Null terminate the string
// Create the process with CREATE_BREAKAWAY_FROM_JOB to overcome the AccessDenied issue on AssignProcessToJobObject.
if(CreateProcess(NULL, path, NULL, NULL, FALSE, CREATE_BREAKAWAY_FROM_JOB|CREATE_SUSPENDED, NULL, NULL,&StartupInfo, &ProcessInfo))
{
pList = (PJOBOBJECT_BASIC_PROCESS_ID_LIST)GlobalAlloc(GMEM_FIXED, 10000);
HANDLE jobObj = CreateJobObject(NULL, (const wchar_t*)jobName.utf16());
if (AssignProcessToJobObject(jobObj, ProcessInfo.hProcess) != 0)
{
ResumeThread(ProcessInfo.hThread); // Process assigned to JobObjext, resume it now
do
{
QueryInformationJobObject(jobObj, JobObjectBasicProcessIdList, pList, 10000, NULL);
bJobAllEnd = TRUE;
for(DWORD i=0; i<pList->NumberOfProcessIdsInList; i++)
{
hProcess = OpenProcess(SYNCHRONIZE, FALSE, pList->ProcessIdList[i]);
if(hProcess != NULL)
{
CloseHandle(hProcess);
bJobAllEnd = FALSE;
}
}
Sleep(500);
} while(!bJobAllEnd);
}
else
qDebug() << "AssignProcess to Job failed: error = " << QString::number(GetLastError());
GlobalFree(pList);
CloseHandle(jobObj);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
}
}
catch(QString error)
{
QMessageBox::critical(this, "File not found!", "The requested uninstaller doesn't exists", QMessageBox::Ok);
}
// refresh list
handleButton();
}
}

run a process with c++, filtering output AND get result code AND get system errors, all together

I want to run another program from c++, redirecting its output to a file and return its result code.
But if I fail to run the program (incorrect path etc.) I want to know.
Here is my problem, how can I: redirect a file, get the result code of the program, get the errors of the system, all at once?
System(): returns the result and is easy to redirect, but there is no way to know if the result is a system error or the application result
posix_spawn(): I know if there is a system error, but how to get the application result code ?
Note that I don't control the code of the executed application
It's easy with Windows (sorry...) OpenProcess() function, what I need is OpenProcess() under linux.
Thanks
You will need to use the posix_spawn function.
The waitpid system call will help you to get the exit code.
See this question.
pid_t waitpid(pid_t pid, int *status, int options);
What you need to do is pretty match standard fork-exec call plus file redirection:
int pid = fork();
if( pid == -1 ) {
// process error here
}
if( pid == 0 ) {
int fd = open( "path/to/redirected/output", ... );
::close( 1 );
dup2( fd, 1 );
::close( fd );
exec...( "path to executable", ... );
// if we are here there is a problem
exit(123);
}
int status = 0;
waitpid( pid, &status, 0 );
// you get exit status in status
By exec... I mean one of the exec functions family (type "man 3 exec" for information), choose one that fits you better.
If you need to redirect error output do the same, but use descriptor 2. You may want to put waitpid() in the loop and check if it is not interrupted by signal.

How do I find out if a .exe is running in c++?

How can you find out if an executable is running on Windows given the process name, e.g. program.exe?
The C++ standard library has no such support. You need an operating system API to do this. If this is Windows then you'd use CreateToolhelp32Snapshot(), followed by Process32First and Process32Next to iterate the running processes. Beware of the inevitable race condition, the process could have exited by the time you found it.
I just created one using Hans suggestion. Works like a champ!
Oh and here is the basic code.
Please you will have to add CStrings sAppPath and sAppName.
StartProcess is a small function that uses CreateProcess and returns the PID(not used here). You will need to replace it.
This is not a complete program, just the code to find if the program is running using Hans suggestion. A fun test is to set the path to c:\windows\ and the app to notepad.exe and set it for 10 seconds.
#include <tlhelp32.h>
PROCESSENTRY32 pe32 = {0};
HANDLE hSnap;
int iDone;
int iTime = 60;
bool bProcessFound;
while(true) // go forever
{
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
pe32.dwSize = sizeof(PROCESSENTRY32);
Process32First(hSnap,&pe32); // Can throw away, never an actual app
bProcessFound = false; //init values
iDone = 1;
while(iDone) // go until out of Processes
{
iDone = Process32Next(hSnap,&pe32);
if (strcmp(pe32.szExeFile,sAppName) == 0) // Did we find our process?
{
bProcessFound = true;
iDone = 0;
}
}
if(!bProcessFound) // if we didn't find it running...
{
startProcess(sAppPath+sAppName,""); // start it
}
Sleep(iTime*1000); // delay x amount of seconds.
}
Assumptions: since you mention '.exe', you want this for some flavor of Windows. You want to write a program in C++ to determine whether a program with a particular executable name is running (regardless of the language used to implement the target program).
Enumerate the running processes using either the Toolhelp API or the process status API. Compare the name of the executable for each running process to the one you're looking for (and be aware that there may be more than one process with that executable name).
hProcessInfo = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
do{
if(strcmp(pe32.szExeFile,"process.exe") == 0)
{
processfound = true;
break;
}
}while( Process32Next( hProcessSnap, &pe32 ) );
If you don't want to get process detail from code just press Ctrl+Alt+Del and check process list.