How to tell if a process started with CreateProcess is still running? - c++

If I've got a process created through CreateProcess(), how would I determine if it's still running? I know I need to use pi.hProcess but I don't know how, and google isn't really giving me meaningful hints.
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
bool got_it=CreateProcess(NULL, CA2T(launchString.c_str()), NULL, NULL, false, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);

You can use any of the standard wait functions, like WaitForSingleObject(), eg:
switch (WaitForSingleObject(pi.hProcess, 0))
{
case WAIT_OBJECT_0:
// process has terminated...
break;
case WAIT_TIMEOUT:
// process is still running...
break;
}

You can retrieve the process's exit code with GetExitCodeProcess(), which will give the special STILL_ACTIVE value if the process is still running:
DWORD exit_code;
GetExitCodeProcess(pi.hProcess, &exit_code);
if (exit_code == STILL_ACTIVE) {
}

Related

Why does the CreateProcess() function not work?

I am trying to call the CreateProcess function to execute some powershell command. The function doesnt return any errors but it doesnt execute the command (there is no file created after running the app). Here is the code.
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
// Start the child process.
if (!CreateProcess(NULL, // No module name (use command line)
const_cast<LPTSTR>(TEXT("powershell.exe -command echo Hello > D:\\out.txt")), // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
std::cout << ("CreateProcess failed (%d).\n", GetLastError());
}
WaitForSingleObject(pi.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

Create process from service

I'm calling GhostScript(GS) command line tool from C++ code with WinAPI CreateProcess function. When I'm running my application as 'common' executable file, everything works fine, but when I'm running my app as service, something goes wrong - GS process creates and it's listed in task manager processes list but then nothing happens. If I run my application as a service on Windows 7 it works correctly, but on Windows 10 the above problem occurs. Code listed below. I will be grateful for any advice.
std::string cmd = ("gswin32c.exe -sDEVICE=mswinpr2 -dBATCH -dNOPAUSE -dNOSAFER -dNoCancel=true -sOutputFile=\"%printer%HPLJ2000\" \"1.pdf\"");
SECURITY_ATTRIBUTES sa;`sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
auto dwFlags = FILE_ATTRIBUTE_NORMAL;
STARTUPINFOW si;
GetStartupInfoW(&si);
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
ZeroMemory(&pi, sizeof(pi));
if (!CreateProcess(NULL, cmd.c_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) {
std::err << "Something went wrong" << std::endl;
}
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
Your process is probably running on the wrong desktop.
There's a bunch of stuff you need to do to fix this. Full example code here:
https://stackoverflow.com/a/50743993/5743288

how to make a child process "independant" from the main process in c++ on windows

i have this function to create a new process
void replicate()
{
STARTUPINFO si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
CreateProcess(NULL, ::GetCommandLine(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
}
i would like to new if it's possible to make my new process like independant of the main process
for example, if i kill the main process, is it possible to make my child processes keep running ?
i will really appreciate your help

CreateProcess returns true but does not execute with regedit

I am trying to dump a portion of the windows registry in a .txt file using the CreateProcess function. The code is along the lines of
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
CString cmdLine = "\"C:\\WINDOWS\\regedit.exe\" /e \"c:\\dump\\TestReg.txt\"
\"HKEY_LOCAL_MACHINE\\SOFTWARE\\MYSOFT\\\"";
LPSTR pCmdLine = (LPSTR)(const char*)cmdLine;
BOOL oc = CreateProcess(NULL, pCmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if(oc == TRUE)
{
WaitForSingleObject(pi.hProcess, 1000);
GetExitCodeProcess(pi.hProcess, &exitCode);
if(exitCode != 0) ret = -1;
}
What I know
The CreateProcess returns TRUE and the last blocks executes
The process waits for the end and exits normally
However no file is produced at the end
The command line string works fine in command line, even when it operates from the same directory where the program is operating.
I have found something that is potentially useful where someone had basically the same problem. In the end it resulted in a dependency clash but the link does not explain very well how it was detected or fixed.

Create Process default browser

I'm currently using ShellExecute "open" to open a URL in the user's browser, but running into a bit of trouble in Win7 and Vista because the program runs elevated as a service.
I want to get thread id so ShellExecute is not possible to get thread id so i started using "CreateProcess" But i don't see any help on opening default browser whichever is it from CreateProcess.
You can use other features of the Shell API to figure out which browser is the default.
For instance, you can ask the shell for the executable name associated with .html files using AssocQueryString, and launch that via CreateProcess.
Here you can open the URL with your default browser.
STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
CStringA command_line;
command_line.Format("cmd.exe /c start \"link\" \"%s\"", "http://www.google.com");
if (!CreateProcessA(NULL, // No module name (use command line)
command_line.GetBuffer(),
NULL, // Process handle not inheritable
NULL, // Thread handle not inhberitable
FALSE, // Set handle inheritance to FALSE
NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
TRACE("CreateProcess failed (%d).\n", GetLastError());
return;
}
Here is another answer as you wanted. As far as you want it open as a new window. You can expand it for IE, opera, and so on...
DWORD size = MAX_PATH;
char buff[MAX_PATH];
int err = AssocQueryStringA(ASSOCF_INIT_IGNOREUNKNOWN, ASSOCSTR_EXECUTABLE, ".html", NULL, buff, &size);
STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
CStringA command_line;
CStringA target_url( "http://google.com/" );
if( strcmp( "chrome.exe", PathFindFileNameA(buff)) == 0 )
command_line.Format("%s --new-window %s", buff, target_url);
else if( strcmp( "firefox.exe", PathFindFileNameA(buff)) == 0 )
command_line.Format("%s -new-instance %s", buff, target_url);
else
command_line.Format("%s %s", buff, target_url);
if (!CreateProcessA(NULL, // No module name (use command line)
command_line.GetBuffer(),
NULL, // Process handle not inheritable
NULL, // Thread handle not inhberitable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
//... error handling
return;
}