Background Information: I'm developing an Windows 10 app. Within my app, some outputs are displayed onto a window console requiring a new process.
Code Snippet:
PROCESS_INFORMATION pi;
STARTUPINFO si;
// CreateProcess is defined in processthreadsapi.h
BOOL newProcess = CreateProcess (
0, pszCmdLine, 0, 0, FALSE, DEBUG_THIS_ONLY_PROCESS, 0, 0, &si, &pi
);
In the above code snippet, pszCmdLine can be "cmd.exe /c dir", "cmd.exe /c ipconfig", or essentially any Windows terminal cmd.
Problem: On the front end, a new cmd console is generated and the user is able to terminate it. However, it's kept alive in the background. I've attached snips below:
Before Process Accumulating:
In the above snip, it shows "cmd.exe /c dir" being executed and outputted into a cmd console.
After Processes Accumulates:
In the above snip, it shows how I launched the same cmd 4 times and closed it 3 times (i.e. the counter is "(4)" including the main process).
Real World Problem: This is essentially consuming memory and has the ability to degrade performance.
Initial Curiosity: Shouldn't the Windows OS handle the killing of this process when the user clicks the "x"?
Has anyone faced a similar issue before?
Solution:
Change DEBUG_ONLY_THIS_PROCESS to 0 or CREATE_NEW_CONSOLE.
My Thoughts:
I suppose the idea behind DEBUG_ONLY_THIS_PROCESS is to leave the window handle open for the user to observe the output whereas CREATE_NEW_CONSOLE allocates and frees the memory as needed.
Related
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.
Python can start an executable file but not C++.
Python -
os.system('cmd /c "start FlaskServer.exe"')
C++ - (I tried 4 different versions)
system("cmd /c \"start FlaskServer.exe\"");
system("start FlaskServer.exe");
ShellExecute(0, L"open", L"cmd", L"/c \"start FlaskServer.exe\"", 0, 0);
ShellExecute(0, L"open", L"FlaskServer.exe", 0, 0, 0);
Note - The file I am trying to execute is a no GUI no console app(flask server) coded in python. It had no GUI I compiled it as GUI to avoid console. In python, it gets opened as a background process but in c++, not listed in the tasklist. Although, other programs with GUI are running fine.
The problem was that being new to c++, I did not knew how to use Win32 buttons. I created WM_command with 2 button events, one for starting the application and other for killing it. I did not put "return 0" at the end. So, it first executed and the killed by the application.
I have been trying to create a cmd.exe from a c++-program and then being able to execute commands from the program inside the cmd.exe, so I can view the results of the operation in the cmd.exe. CreateProcessA() is the function I used:
_STARTUPINFOA CMD_StartupInfo = {};
CMD_StartupInfo.cb = sizeof(_STARTUPINFOA);
_PROCESS_INFORMATION CMD_ProcessInfo = {};
CreateProcessA("C:\\Windows\\System32\\cmd.exe",
0,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&CMD_StartupInfo,
&CMD_ProcessInfo);
The cmd.exe opened and it looked to be working. Then I thought I'd use PostMessage() to pass WM_KEYDOWN messages to the cmd.exe to execute a command. For this function I needed a window handle and it turns out that the process of getting a window handle from a process/thread ID which is obtained from the CreateProcessA() is f***ing complicated. You have to loop through all active windows with EnumWindows() that requires a callback function which needs to check whether or not the process ID of the current window is the same as the process ID of the process I created.
I did that and it turned out that none of the windows the function iterated over were my window.
So I presume that means that the thread of this process which I created has no windows but I can see a beautiful-looking cmd.exe right there. What is going on? Is this not considered a window? If not, how do I pass messages to the cmd.exe and if yes, how do I get the window handle?
Any help is appreciated (also ideas to do the entire cmd-thing differently).
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.
I am relatively new to C++ programming and currently using Visual Studio 2012 API. My OS is Windows 7 64-bit. I would like to write a program in C++ which displays a message box or window with a simple shutdown message e.g. 'shutting down.....' or something similar when I close a specific application. This window I am hoping will appear for the duration of the app exit time and then close.
Is it possible to create a handle which will retrieve the exit time for a running application when it is abruptly closed? And if so, how could I use this exit time in a statement which will display the message box?
I would appreciate constructive criticism as I am new to this language. Thank you sincerely for any advice you impart. If requested, I will display all source code.
I don't think this is the right way to go about this but anyway, below is a snippet of the code which I have been toying with, as part of a greater VS Win32 application project:
LPTSTR lpchText(_T("Shutting down...."));
LPFILETIME lpExitTime = 0; //Initialise
TCHAR Buffer[_MAX_PATH];
DWORD size = _MAX_PATH;
LPCTSTR lpStr(_T("C:\Program Files\Common Files\ExampleApp.exe")); // Path to executable app.
AssocQueryString( ASSOCF_OPEN_BYEXENAME,
ASSOCSTR_EXECUTABLE,
lpStr,
NULL,
Buffer,
&size
);
GetProcessTimes(
AssocQueryString,
NULL,
lpExitTime,
NULL,
NULL
);
while(lpExitTime){
MessageBoxEx(
_In_opt_ hWnd,
_In_opt_ lpchText,
_In_opt_ lpCaption,
_In_opt_ MB_ICONEXCLAMATION
,0
);
};
return TRUE;
enter code here
I guess shutting down the application is a lengthy operation othervise a normal application will be closed so fast that the user will have no chance to actual see the window.
But of course it possible, in meta code this is the steps.
Attach to the running process. You can enumrate the running process from the name of the executable to find the correct process.
Once you have the handle to the process you can attach to the process message loop.
Listen for the WM_QUIT (assuming it is a Windows applictaion) message and then display the window.
Wait for the process handle using MsgWaitForMultipleObject, the function will signal when the process terminates.
Attaching to other processes has some security issues so it might not work for a regular user.
Other options to explore is to handle it in a power Shell script or make a small launcher application that in turn starts the actual application.
Is it an option to modify the application itself to have this functionality?