I've created a Windows/C++/WTL application that spawns a child process. The two processes communicate via anonymous pipes.
I'd like to be able to debug the child process.
Since both parent and child projects are in the same solution in Visual Studio 2008, is there any way to tell VS2008 that I'd like the debugger to debug both processes?
When I start the debugger with the parent process, the debugger won't break on any breakpoints in the child process code.
And since the child process is spawned by the parent process, I can't think of an easy way of attaching the child process (maybe via another instance of VS2008) when it's spawned.
Any insights greatly appreciated!
Plenty of options:
You can debug multiple .exes with one instance of the debugger by using Debug + Attach. I however always use two instances of Visual Studio, use Debug + Attach in the second one.
You could put a __debugbreak() in the child's code, the JIT debugger window will prompt you to select a debugger.
You can use the "Image File Execution Options" registry key to automatically launch a debugger as soon as the child .exe is started. Add a key named HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\YourApp.exe, set its "Debugger" value to "vsjitdebugger.exe"
There is a VS add-in that makes it easier yet, haven't tried it myself yet.
You can temporarily put in a call to DebugBreak() somewhere in the startup code of your child process. This will cause Windows to prompt you if you want to debug that process.
You could put a global named mutex around your CreateProcess call, and then try to grab the mutex in the child process. If you then put a breakpoint on the CreateProcess call, you should have time to attach to the child before it does anything substantial.
Note that you would miss anything that happens before main in the child process.
edit: As an example, something like this, untested:
// parent.cpp
HANDLE hMutex = ::CreateMutex(NULL, TRUE, "Global\\some_guid");
::CreateProcess(...);
::ReleaseMutex(hMutex); // breakpoint here
::CloseHandle(hMutex);
// child.cpp
int main(...)
{
HANDLE hMutex = ::OpenMutex(MUTEX_ALL_ACCESS, FALSE, "Global\\some_guid");
::WaitForSingleObject( hMutex, INFINITE );
::CloseHandle(hMutex);
...
}
You would probably want to wrap it with #if _DEBUG or environment variable checks.
Related
I have a Win32 C++ application. I'm trying to launch one or several child processes with CreateProcess. I want the children to close when the parent does.
I achieved this by creating a job and enabling JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE:
HANDLE hJob = CreateJobObject(NULL, NULL);
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo;
ZeroMemory(&extendedInfo, sizeof(extendedInfo));
extendedInfo.BasicLimitInformation.LimitFlags =
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
SetInformationJobObject(
hJob, JOBOBJECTINFOCLASS::JobObjectExtendedLimitInformation,
&extendedInfo, sizeof(extendedInfo));
Then adding the current (parent) and created (child) process to this job:
// assign parent to job
AssignProcessToJobObject(hJob, GetCurrentProcess());
// launch child with no inherited handles
PROCESS_INFORMATION procInfo;
ZeroMemory(&procInfo, sizeof(procInfo));
STARTUPINFOA startInfo;
ZeroMemory(&startInfo, sizeof(startInfo));
startInfo.cb = sizeof(startInfo);
startInfo.dwFlags |= STARTF_USESTDHANDLES;
bool success = CreateProcessA(NULL,
"test.exe", // command line
NULL, // process security attributes
NULL, // primary thread security attributes
FALSE, // handles are inherited
0, // creation flags
NULL, // use parent's environment
NULL, // use parent's current directory
&startInfo, // STARTUPINFO pointer
&procInfo); // receives PROCESS_INFORMATION
// assign child to job
AssignProcessToJobObject(hJob, procInfo.hProcess);
This works, but the parent app and the child app (main.exe and test.exe) show up as two unrelated processes in the task manager:
(Even though closing main.exe will close test.exe).
What am I doing differently than, say, Microsoft Teams or Chrome, which both have nested processes?
Exactly what Task manager is doing is not documented.
In Windows 8 it does not group child processes, it only organizes based on a process having a window or by being "special".
How does Task Manager categorize processes as App, Background Process, or Windows Process?:
These are terms that Task Manager simply made up. The system itself doesn’t really care what kind of processes they are.
If the process has a visible window, then Task Manager calls it an “App”.
If the process is marked as critical, then Task Manager calls it a “Windows Process”.
Otherwise, Task Manager calls it a “Background Process”.
(I don't believe this is 100% accurate, it clearly knows about services and I suspect it might hard-code some names)
In Windows 10 it tries harder to group things together but I don't exactly know what it is doing.
It is often (but not always) able to tie the conhost.exe child to its parent console application.
The new fancy store/packaged versions of Notepad and Paint have all their processes in a single group. The same does not happen with Notepad2 even though it has a Application Model ID set. Neither does it apply to Wordpad (even when one is a child of the other). I also tried setting an AMUI in a little test application and neither process wide AMUI nor per-HWND AMUI seems to trigger the grouping.
A job object does not seem to enable grouping.
Depending on your version, Edge might use a special API to tell Task manager about its processes.
In conclusion, I don't know what exactly what it is looking for but Packaged applications and App Containers seem to often trigger it.
To make it visible as a child process in the task manager, you have to set the CreateNoWindow property to false and UseShellExecute property to false in the StartInfo property before starting the process.
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
This tells the process to create a new window for the child process and to use the command line to start the process instead of using the shell to start the process.
This will now create the child process as a new visible process in the task manager, and it will be shown under the tree of the main process.
We have an old MFC-based C++ gui app (Visual Studio 6.0) which often does not terminate correctly. So I would like to be able to use a instruction like "abort();" to immediately end it.
However, the abort() instruction causes a dialog box to pop up, rather than ending immediately. Using "exit(int)" doesn't work.
Is there a way to eliminate the abort dialog, or is there a better termination method?
One obvious way to abort without anything else happening ahead of time would be for it to call the Windows ExitProcess function:
ExitProcess(exitCode);
If you want to kill it from some external program, you'd do that with TerminateProcess. To do that, you'll need a handle to the process, which typically means getting its process ID. If you're doing this from a program that spawned the one you want to kill, you'll probably get a handle to it when you create it. Otherwise, you'll probably need to use something like FindWindow to find its window, then GetWindowThreadProcessId to find the ID of that window's process. Once you have that, you call OpenProcess to get a handle, and finally TerminateProcess to actually kill it.
If it is a dialog box based app, then you can use EndDialog(IDOK) method.
Using Visual Studio 2017.
I use
siStartInfo.dwFlags &= STARTF_USESHOWWINDOW;
siStartInfo.wShowWindow = SW_HIDE;
to create a child process (through CreateProcess()) with a hidden window. It works perfectly.
What I would like, if at all possible, is to be able to toggle the visibility status of the child process' window, post-creation, from the main program on demand (with a press of a button, for example). I want to control the child process' window visibility without relaunching it through CreateProcess().
Modifying the child process code is not an option - it can be many different programs with not necessarily available source code.
Thanks in advance.
If you know a unique window class or title of the child process, you can use FindWindow() to find that window.
For a more generic approach, use EnumWindows() to enumerate all top-level windows. For each window call GetWindowThreadProcessId() to check if it belongs to the child process.
Call ShowWindow() to toggle visibility.
I have a windows application which invokes CreateProcess and then it exits. The process being invoked displays console and GUI windows at startup. I would like to hide the console window of the child process right when it starts.
More info:
Process is NOT started with DETACHED_PROCESS flag.
If injecting code with FreeConsole() to the remote process is the only way (I'm looking for a better one), is it not going to cause trouble with over-sensitive anti-viruses?
You can use the CREATE_NO_WINDOW flag to start a console application without a console window. It's not the same as it being hidden, but it sounds like it's what you want.
I have a program that launches a child process.
When the child process crashes I would like there not to be a debug message box. I would like to do this without writing anything in the child process.
I am running this on windows 7.
In the createProcess function, in the flags parameter I only put CREATE_NEW_CONSOLE.
During my attempts, I put SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX) in the child process and made it crash, there was no dialog box. Now I put the same function call in the parent program before I called create process, and made the child program crash, now the message box appeared.
What should I do differently?
have you set CREATE_DEFAULT_ERROR_MODE in process creation flags?