how to show console app window hidden by createprocess function - c++

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);
}

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.

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)

Setting a HWND's lpfnWndProc from another process

I have a win32 main application that spawns a child process.
At the moment I use CreateWindowEx to create a HWND in the main application followed by spawning a child process. The child process then looks up the HWND using FindWindow. I would like to handle the Window messages (e.g. WM_SIZE, WM_SETFOCUS etc) for this HWND in the child process, therefore I tried setting the GWLP_WNDPROC attribute in the child process but I'm getting an access denied error, which is reasonable.
I thought about creating a HWND directly in the child process instead but when the window is clicked on, the main application loses focus which is not acceptable for my use case.
Does anyone have a suggestion on what to do to keep the focus on the main application, while having the child process handling the messages?
Use SetWindowsHookEx with one of the windows message hooks (e.g. WH_CALLWNDPROC) to intercept the messages going to other windows, then filter by the HWND of the window in question.
In your child process you can call ShowWindow with WS_NOACTIVATE. When calling CreateProcess function you can specify STARTUPINFO as follows:
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNOACTIVATE;
You can even explicitly give back focus in your child application to main window.
I suppose you want to have similar design to what chromium does. If you look closely at their design docs:
http://www.chromium.org/developers/design-documents/inter-process-communication
you will see that they do implement IPC between processes but they do not have single message processing function in main process.
As last hint - not related to question, read on jobs under windows - this mechanism allows to take a closer control on child processes.

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.

How to launch console application using CreateProcess with Minimized main window

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;