I have two processes: ProcessA and ProcessB.
When i launch my application, i call ProcessA which uses CreateProcess() to launch ProcessB. ProcessA is killed by ProcessB when my application receives command A. Likewise, ProcessB should relaunch ProcessA when it receives command B.
Where i am stuck on is on the process of relaunching ProcessA. Since ProcessA has the code to relaunch ProcessB, i cannot stop it from relaunching another instance of ProcessB. Ideally, i want to have only 1 instance of ProcessB.
For creating ProcessB from ProcessA, i have the following code:
for(int i32Index = 0; i32Index < NUM_PROCESS; i32Index++)
{
wcscpy(wcPath,Directorypath.c_str());
wcscat(wcPath,wcProcess[i32Index]);
RETAILMSG(1,(_T("Path:%s\r\n"),wcPath));
bCreateProcessSuccess = CreateProcess(wcPath, // No module name (use command line)
NULL, // 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
if(bCreateProcessSuccess == FALSE)
{
RETAILMSG(1,(_T("Create process failed:%d\r\n"),GetLastError()));
}
else
{
RETAILMSG(1,(_T("Loading Exes\r\n")));
}
Pretty straightforward, basic code. I basically repeat this in ProcessB, but so that it creates ProcessA.
Now, im stuck on how i would be able to implement the condition to launch ProcessA without it launching ProcessB again. I initially thought of using a flag, but that flag would be reset since launching ProcessA would reset the flag as it is local to the function.
Also, to clarify: this is in windows embedded compact environment so both processes exist as different subprojects so to access ProcessA from ProcessB would require IPC.
My next idea was to use CreateEvent() with WaitForSingleObject() to check if the event is signaled, but i realized that the wait duration would have to be infinite, which would cause an issue the first time i launch my application.
So, is there any type of windows(wince) api that would solve this? (Or some kind of fancy coding i cannot think of?)
There are a few ways you could do this but two options are:
When you launch ProcessA again, pass it a command line argument using the lpCommandLine parameter (e.g. /nolaunch). ProcessA can then get its command line using GetCommandLine when it starts up and see if it contains the /nolaunch string.
In both ProcessA and ProcessB, use the CreateSemaphore or CreateMutex function to create a named semaphore/mutex. In ProcessB, that's all you have to do - just make sure you don't close the handle until the process exits. In ProcessA, after creating the semaphore/mutex check if GetLastError() returns ERROR_ALREADY_EXISTS - this indicates that ProcessB still has the semaphore/mutex open (and therefore is already running).
There are multiple ways you can sole this:
1. Holding a mutex
In processB you can hold a named mutex and lock it. When processB will be created, it will try to lock the mutex and fail, and than it will kill itself. You can also check if the mutex is locked in processA and prevent the processB creation from the beginning.
2. Sending an argument to process creation
CreateProcess supports sending command line arguments to the created process via the second argument. You can use it as an indicator to whether you should create processB or not.
3. Going through the process list
You can go through the current process list and check if ProcessB is already running. Might want to look into Taking a Snapshot and Viewing Processes.
Related
I need to execute processes with still being in control of each process.
I want to create a class which stores the threads or pids or what ever is necessary to do so.
I currently have a program which executes one external application with the C function execvp and also loads the environment from a shell script. So my current program is blocking. But I need to be able to keep it freely running and only by time I terminate a currently running or start a new external application.
My current approach would be to create a thread, which uses the execve function. But then the thread would be blocking as far as I can see.
The code which might be in the thread (with variables then):
char *argv[] = { "/bin/bash", "-c", "myApplication", 0 };
execve(argv[0], &argv[0], environment.data());
The applications called are probably not fixed in the code their names will be given by an external setup file, including parameters.
Now my actual question, is there a better way to "manage" external applications like that in c++? Some ready solution (class, library)? And if not how do I terminate the thread if this is the actual way. Using the terminate call is said to be bad practice, that's what I often read.
I hope this is now specific enough for the forum, because I do not know how to get more specific anymore. If you need more hints what I want to create here, feel free to ask in the comments.
Update:
to DBus & others:
Additional information I do not wrote all of the processes I want to start!
So it will be used to start 3rd party applications, which even if I have the code, do not want to change.
You want to fork() before you exec. fork() is a function that creates a new process identical to the original caller of fork() running as a subprocess. The difference is that the parent process gets the child's pid as a return value and the child gets 0. The gist of what you want to do is this:
pid_t pid = fork();
if( pid == 0 )
{
// we're the child process
char *argv[] = { "/bin/bash", "-c", "myApplication", 0 };
int rc = execve(argv[0], &argv[0], environment.data());
// execve only returns if there was an error
// check 'errno' and handle it here
}
else if ( pid < 0 )
{
// pid is less than zero, we didn't successfully fork,
// there is no child process.
throw "error message";
}
// do whatever processing the parent does
More info is here. The kill() function isn't bad practice per se, if you want to quickly and gracefully end the subprocess you can write signal handlers in it, but you should be using something like dbus or zeromq to do proper interprocess communication. You want to tell the program to do something, not just tell it to die (usually what you want it to do if you're killing it).
NEVER USE execv functions in threads because the execve() system call overlays the current process image with a new process image.
The correct pattern if fork-exec or better vfork-exec. Extract from the manpage:
The vfork() system call can be used to create new processes without fully
copying the address space of the old process, which is horrendously inefficient in a paged environment. It is useful when the purpose of fork(2)
would have been to create a new system context for an execve(2). The
vfork() system call differs from fork(2) in that the child borrows the
parent's memory and thread of control until a call to execve(2) or an
exit (either by a call to _exit(2) or abnormally). The parent process is
suspended while the child is using its resources.
Using vfork shortly followed with execve, you avoid the copy of the original process image, and do not erase if with the new process, so the original process has the pid of its child and cat control it, look whether it has ended, send it signals and so on.
Can someone please explain to me what is the differance between:
OpenProcess and CreatProcess.
(I am trying to inject a DLL into a program and I dont know which one to use.)
OpenProcess is passed a process ID for an existing process, and returns a process handle for that process.
CreateProcess creates a brand new process, returning a handle to that new process (amongst other things).
If you want to inject into a process that is already running, then you will need OpenProcess.
In relation to injecting a .dll into another process,there are a couple of major benefits and differences between OpenProcess and CreateProcess.
The first is timing. You can inject the dll before the target process has had a chance to perform any of their own code by creating the process in a suspended state (dwCreationFlags with CREATE_SUSPENDED(0x00000004) set). Don't forget to resume the process once you are ready for it to execute.
The second is privilege. The process handle returned by CreateProcess automatically has PROCESS_ALL_ACCESS without the need to set SeDebugPrivilege first. OpenProcess does require your program to gain this privilege before it is allowed to use the PROCESS_ALL_ACCESS flag.
Some other minor things to remember:
CreateProcess cannot be called on a running process, but you can always call OpenProcess after CreateProcess if you needed to for whatever reason.
CreateProcess requires you to CloseHandle both the process and thread handles returned in PROCESS_INFORMATION, where OpenProcess only requires you to CloseHandle on it's return value (No thread handle gets opened).
If you need to change the Environment for whatever reason(unlikely), you'll have to use CreateProcess.
Further reading can be found:
CreateProcess
OpenProcess
process-security-and-access-rights
I need to get the PROCESS_INFORMATION of an external process for use in my application, I have the process handle and process ID, but I don't know how to go about getting the PROCESS_INFORMATION out of that.
I'm using C++(11), Visual Studio 2012, running on Windows. Any help would be greatly appreciated.
PROCESS_INFORMATION is filled by CreateProcess(). That ship has sailed; the process was already started.
Let's focus on what you really want to do. To find out if a process has terminated, first use OpenProcess() to obtain a handle to the process. You'll need the PID, which you already have. Then WaitForSingleObject() will tell you if it is terminated. Pass INFINITE for the 2nd argument to block until the process terminates. Pass 0 if you want to poll. Finally, use CloseHandle() to clean up.
PROCESS_INFORMMATION provides 4 pieces of information:
HANDLE hProcess
HANDLE hThread
DWORD dwProcessID
DWORD dwThreadID
You say you already have two of those values - the Process Handle and Process ID. So that just leaves the Thread Handle and Thread ID. Those belong to the first thread created for the process. You can use CreateToolhelp32Snapshot(), Thread32First(), and Thread32Next() to enumerate the running threads looking for Thread IDs that belong to a given Process ID, and then use OpenThread() to get the Thread Handle of a given Thread ID. The tricky part is identifying which Thread ID is the first thread. That information is not readily available outside of CreateProcess().
The information you need can be obtained with the CreateToolhelp32Snapshot function since it returns both the process ID and the parent process ID. An example of its use can be found here.
I am using CreateProcess function for creating the process, is there any option to get the current state of the process (running or not). Kindly guide me how can I make it possible.
Use OpenProcess function with that dwProcessId if it returns NULL Process is not running otherwise it will return handle to that process
Create process returns a handle to the process in PROCESS_INFORMATION structure, you can use this with something like GetExitCodeProcess to work out if it is still running, or you can use the wait functions to wait for it to exit.
I'm using the ShellExecuteEx function in a C++ program to launch an Uninstall.lnk file. In my program, I'd like to wait for the uninstaller to finish. My first attempt was to set the SEE_MASK_NOCLOSEPROCESS flag in the SHELLEXECUTEINFO structure and then call WaitForSingleObject on the hProcess handle available in the SHELLEXECUTEINFO structure passed to ShellExecuteEx, but that still seemed to return way too early.
My current suspicion is that this is because the process launched by ShellExecuteEx (does it launch a new shell?) creates new child processes, but doesn't wait for them. So I'm trying to create a "wait for my child process and all the children it launches" function. To do so, I'm trying to use job objects.
I created a job object using CreateJobObject, assigned the process handle returned by ShellExecuteEx to the job and then attempted to wait for the job object. Unfortunately assigning the process to the job failed, and I think this is due to insufficient access rights.
Does anybody know how to set the PROCESS_SET_QUOTA and PROCESS_TERMINATE access rights (which are required for AssignProcessToJobObject to succeed, according to the MSDN) on a process handle, or another way to wait for the process launched by ShellExecuteEx to finish?
UPDATE: I should point out that I'm also launching other applications, not just Uninstall.lnk. One of them is e.g. a ClickOnce application, which is effectively a simple XML file with the file extension .application.
Vista uses job objects for launching links. Therefor the process you try to assign to another job object might already be assigned.
See: this question
Why not to execute target file instead of openning Uninstall.lnk? You could use IShellLink to get shortcut target. Then you'll be able to execute target file via ShellExecuteEx using SEE_MASK_NOCLOSEPROCESS flag.