How to launch console application using CreateProcess with Minimized main window - c++

I have a native c++ windows application that is launching two child processes using the following code -
if (!CreateProcess(NULL, // No module name (use command line)
cmdLine, // szCmdline, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
false, // Set handle inheritance to FALSE
CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS // Process Create Flags
NULL, // Use parent's environment block
NULL, // workingDir, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
with all parameters in STARTUPINFO block 0. This code works fine in launching the processes. However, I need to be able to launch the windows c++ console applications with their windows minimized.
If I add CREATE_NO_WINDOW to the Process Create Flags, I can launch the processes without any windows. This will be unacceptable.
In my research, there does not appear to be a way force a console application to open in a minimized mode. Is this correct?
Yes, I know that I could minimize the child application windows from within their own process, however, the other programmers on the team prefer not to do this.

You need to specify in the STARTUPINFO structure that you want your console window to be initially minimized:
ZeroMemory(&si);
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_MINIMIZE;

Related

CTRL_BREAK_EVENT to a GUI application will compromise parent process

I created a console application with code beneath.
Those code will just start a child process of the explorer.exe then send a CTRL_BREAK_EVENT to it which is expected to be a NO-OP since the child explorer process is not a console application. Then using TerminateProcess to kill the child process which had no effect either but it's ok too.
The problem is, after those steps, the whole console event system for this parent process is broken - I cannot shutdown this console application by clicking X on the console window nor by pressing CTRL-C.
#include <Windows.h>
#include <iostream>
int main() {
const LPWSTR exe = const_cast<LPTSTR>(TEXT("C:\\Windows\\explorer.exe"));
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
CreateProcess(exe,
exe,
NULL,
NULL,
FALSE,
CREATE_NEW_PROCESS_GROUP,
NULL,
NULL,
&si,
&pi);
Sleep(1000);
GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pi.dwProcessId);
Sleep(1000);
TerminateProcess(pi.hProcess, 0);
Sleep(1000);
while (true) {
Sleep(1000);
std::cout << "Hello World!\n";
}
}
I do this because I'm making an application hosting platform that people can upload and run applications on a private cloud. We don't know what kinds of EXEs users will upload. If user uploads a console application that relying on CTRL_BREAK_EVENT for a graceful exit, we want to make it possible, so we try CTRL_BREAK_EVENT first. If the program doesn't shutdown in time after a while (for example a GUI program) we will kill it, just like the code above did. We don't want it to break the whole console control event system if we do this on a GUI application since we rely on it to manage lifecycles other services which run as children processes.
By the way, if we created the process with creation flag "DETACHED_PROCESS", the breaking of console control event system will break too even the EXE is a console application.
Any idea to workaround this?
Many thanks!
This is a workaround to prevent this issue from occuring which I use currently in our production, for anyone who is facing the same issue.
Use QueryFullProcessImageName to find the PE image file path of the child process.
Find the subsystem of this PE image. https://learn.microsoft.com/en-us/windows/win32/debug/pe-format
If the subsystem is GUI, don't use GenerateConsoleCtrlEvent on it.
If you are not familiar with PE format and don't want to read the doc, just do this:
Read at 0x3c as UINT16 of the PE file to find the offset of PE header.
Read UINT8 at PE_HEADER + 0x18 + 0x44, and 0x02 means a GUI application.
I would like to not mark this as an answer since I'm hoping some more elegant way.

Windows: kill program that creates itself

I've accidentally created a program that continues to call CreateProcess on itself - resulting in an infinite loop.
How would I go about killing this program once it's started to run? I have attempted killing this through the task manager, but because the program calls itself to start and immediately dies, it continues to disappear and reappear in the task manager making it 'unstoppable'.
The only way to stop this seems to be a reboot of the PC, which can be very inconvenient.
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow )
{
using namespace std;
CreateProcess( L"self.exe",
NULL, // No command line arguments
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
NULL, // Set handle inheritance to NULL
NULL, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&lpStartupInfo, // Pointer to STARTUPINFO structure
&lpProcessInfo // Pointer to PROCESS_INFORMATION structure
);
return 0;
//return (int)msg.wParam;
}
From a end-users point of view, the easy solution is to press Ctrl+Alt+Del and log off. If you want to keep the session alive the only solution to a fork-bomb like this is to use a tool that understands the process tree. taskkill /T /IM self.exe as suggested in the comments or the "Kill process tree" feature in Process Explorer. Child processes might still be able to sneak past so you might have to execute the kill command multiple times.
If I was programming a kill tool for this I would enumerate the processes and when a target process is found you open a handle to it and try to associate it with a job object. A job object allows you to deny the creation of child processes and allows easy termination of all processes in the job. Just call TerminateProcess if the process could not be added to a job.
You need to run this enumeration code in a loop until you have killed all the desired processes.

How to start an application as a child of a newly created explorer process?

I'm working on an application that resembles a kiosk. After the application starts, it creates a new desktop with limited capabilities. Using a key combo I can move back and forth between desktops. In order to inform the user about the desktop it's currently using, or any other information I've created an application, which is displaying balloon messages is System Tray area.
In the newly created desktop, I start an explorer.exe using CreateProcess function, and providing the new desktop thru a STARTUPINFO structure, and I'm returning a handle for the process in a PROCESS_INFORMATION structure.
Using the same technique I'm trying to start the icon tray application in the new desktop , providing the new desktop in the STARTUPINFO structure. The trouble is that, according to the task manager, the application is running, but the tray icon is not displayed.
My intuition says that in the new desktop, the icon is not shown because it's not a child of the new explorer.exe process, the procexp application from live.systernals is showing these two processes, on the same level in a tree representation.
Is there a way to provide an argument to CreateProcess, maybe the explorer process handle, so that the icon tray application starts as a child of this process?
L.E.: Here is the code that I use to create start the explorer.exe and the icon tray processes:
STARTUPINFO sInfoNT; /// startupinfo for the explorer.exe
PROCESS_INFORMATION pInfoNT; /// process infromation for the explorer.exe
ZeroMemory(&sInfoNT, sizeof(sInfoNT));
sInfoNT.lpDesktop = L"threadDesktop"; /// setting the desktop for the process
pInfoNT = startProcess(sInfoNT, L"C:\\Windows\\explorer.exe"); /// starting the process
if (!pInfoNT.hProcess)
LOG(ERROR) << "Unable to start the new explorer process";
else
LOG(INFO) << "Started the new explorer process";
STARTUPINFO sInfoTITD; /// doing the same thing for the tray icon application
PROCESS_INFORMATION pInfoTITD;
ZeroMemory(&sInfoTITD, sizeof(sInfoTITD));
sInfoTITD.lpDesktop = L"threadDesktop";
pInfoTITD = startProcess(sInfoTITD, L"DesktopTrayIcon.exe");
if (!pInfoTITD.hProcess)
LOG(ERROR) << "Unable to start the tray icon for the new desktop";
else
LOG(INFO) << "Started the tray icon for the new desktop";
And this is the startProcess function:
PROCESS_INFORMATION KioskLauncher::startProcess(STARTUPINFO startUpInfo, LPCTSTR lpApplicationName)
{
PROCESS_INFORMATION processInformation;
ZeroMemory(&processInformation, sizeof(processInformation));
if (!CreateProcess(lpApplicationName, NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startUpInfo, &processInformation))
MessageBox(0, L"Unable to start the process!\nThe path is broken!", L"Path Error!", MB_ICONERROR);
return processInformation;
}
If your really want to make the new Process a child of that other process, you have to use code injection. A search for CreateRemoteThread will give you plenty of reading material. The biggest problem is, that your process has to be the same bit-ness as the target. There are 3 ALTERNATIVE ways of using it:
Dll injection (standard)
Inject actual shellcode: Assembler code that will resolve all dependencies itself. (Will not work with EMET enabled)
Copy a block of code from your application and fix the imports (Tricky)

how to show console app window hidden by createprocess function

I have a GUI in c++. The GUI used to start another independent console based application using CreateProcess method. I am hiding these console apps by passing CREATE_NO_WINDOW flag in CreateProcess. Now I want to make it visible again. How do I do that?
Instead of using the CREATE_NO_WINDOW flag, use the wShowWindow member of the STARTUPINFO struct instead. Set it to SW_HIDE initially (and set the dwFlags member to STARTF_USESHOWWINDOW), then you can use ShowWindow() to show/hide the console window when needed. To find the window that belongs to the new process, use EnumWindows() and GetWindowThreadProcessId() to find the window whose process/thread IDs match the IDs that CreateProcess() returns in the PROCESS_INFORMATION struct.
You had one shot at getting the window created and you passed it up. Thats right but you can show or hide gui, after createProcess method.
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&si,sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi);
si.wShowWindow = SW_SHOW;
si.dwFlags = STARTF_USESHOWWINDOW;
si.lpTitle ="my_process_console";
CreateProcess(null,"my.exe",null,null,false,CREATE_NEW__CONSOLE,null,null,&si,&pi);
I created process.Now I use find method and then I can show GUI.
HWND console_name =FindWindow(null,"my_process_console");
if(console_name){
ShowWindow(console_name,SW_SHOW);
}

Combining CreateProcess and AllowSetForegroundWindow on WIN32

I have an application that is essentially a "helper" application that wraps another app.
The app that the user interacts with is a process that is created by the "helper" app like so:
PROCESS_INFORMATION processInfo;
STARTUPINFO startupInfo;
memset(&processInfo, 0, sizeof(processInfo));
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
startupInfo.dwFlags = STARTF_USESTDHANDLES;
startupInfo.cb = sizeof(startupInfo);
int retval = CreateProcess(cmd, cmdLine, NULL, NULL, false,
CREATE_NO_WINDOW, NULL, NULL, &startupInfo,
&processInfo);
This process is an executable that I do not have the source code to and cannot make changes to.
The "helper" application does a few things based mainly on network traffic from the other app. At one point I want to display a file browse dialog from the helper app based on something the user does in the started UI process.
When I show the file dialog from the helper app, it's shown behind the UI of the process that was created, which isn't ideal. I tried calling SetForegroundWindow() from the helper app but it fails the criteria specified for SetForegroundWindow in the MSDN docs ( http://msdn.microsoft.com/en-us/library/windows/desktop/ms633539%28v=vs.85%29.aspx ), namely:
The process is not the foreground process.
The process was not started by the foreground process.
(even though the process created the foreground process).
Is there a way to call CreateProcess() with a flag or setting that works like calling AllowSetForegroundWindow() from that process? Or a flag that can be used to make Windows think the started process is "the same" as the process that started it for purposes of SetForegroundWindow permissions?
Or is there another way I can show the dialog generated by the helper app on top of the created process' dialogs?
The only solution I could think of off the top of my head would be to do remote thread injection into the child process, and then have your injected thread call AllowSetForegroundWindow with the appropriate parameters to allow the parent process to steal foreground-ness back.
I have not tested this though.