how to terminate a process created by CreateProcess()? - c++

I have created a process using CreateProcess(). This is the code:
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
result = CreateProcess("C:\\AP\\DatabaseBase\\dbntsrv.exe", NULL, NULL, NULL, FALSE, 0, NULL, "C:\\ADP\\SQLBase", &si, &pi)
How can I get the Handle and processId of this specific process? And eventually use it to close this process?
Thank You.

In the struct pi you get:
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;
The first parameter is the handle to the process.
You can use that handle to end the process:
BOOL WINAPI TerminateProcess(
__in HANDLE hProcess,
__in UINT uExitCode
);
hProcess [in]
A handle to the process to be terminated.
The handle must have the PROCESS_TERMINATE access right. For more information, see Process Security and Access Rights.
uExitCode [in]
The exit code to be used by the process and threads terminated as a result of this call. Use the GetExitCodeProcess function to retrieve a process's exit value. Use the GetExitCodeThread function to retrieve a thread's exit value.

A handle to the process is returned in the PROCESS_INFORMATION structure, pi variable.
The TerminateProcess() function can be used to terminate the process. However, you should consider why you need to kill the process and why a graceful shutdown is not possible.
Note you need to set the cb member of si before calling CreateProcess():
si.cb = sizeof(STARTUPINFO);
EDIT:
To suppress the console window specify CREATE_NO_WINDOW, as the creation flag (the sixth argument) in the CreateProcess() call.
EDIT (2):
To suppress the window try setting following members of STARTUPINFO structure prior to calling CreateProcess():
STARTUPINFO si = {0};
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = FALSE;

Closing the process cleanly
To close the process cleanly, you should send a close signal first:
How To Terminate an Application "Cleanly" in Win32.
If you absolutely must shut down a process, follow these steps:
Post a WM_CLOSE to all Top-Level windows owned by the process that you want to shut down. Many Windows applications respond to this message by shutting down.
NOTE: A console application's response to WM_CLOSE depends on whether or not it has installed a control handler.
Use EnumWindows() to find the handles to your target windows. In your callback function, check to see if the windows' process ID matches the process you want to shut down. You can do this by calling GetWindowThreadProcessId(). Once you have established a match, use PostMessage() or SendMessageTimeout() to post the WM_CLOSE message to the window.
Use WaitForSingleObject() to wait for the handle of the process. Make sure you wait with a timeout value, because there are many situations in which the WM_CLOSE will not shut down the application. Remember to make the timeout long enough (either with WaitForSingleObject(), or with SendMessageTimeout()) so that a user can respond to any dialog boxes that were created in response to the WM_CLOSE message.
If the return value is WAIT_OBJECT_0, then the application closed itself down cleanly. If the return value is WAIT_TIMEOUT, then you must use TerminateProcess() to shutdown the application.
NOTE: If you are getting a return value from WaitForSingleObject() other then WAIT_OBJECT_0 or WAIT_TIMEOUT, use GetLastError() to determine the cause.
By following these steps, you give the application the best possible chance to shutdown cleanly (aside from IPC or user-intervention).
See this answer for code.
Terminating the process
If you don't care about clean shutdown, you can use TerminateProcess(). However, it is important to note that TerminateProcess() is asynchronous; it initiates termination and returns immediately. If you have to be sure the process has terminated, call the WaitForSingleObject() function with a handle to the process.
Note: Access rights PROCESS_TERMINATE and SYNCHRONIZE are required.
TerminateProcess(pi.hProcess, 0);
// 500 ms timeout; use INFINITE for no timeout
const DWORD result = WaitForSingleObject(pi.hProcess, 500);
if (result == WAIT_OBJECT_0) {
// Success
}
else {
// Timed out or an error occurred
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
Not closing, just wait until finished
If the process will finish on its own, instead of terminating you can wait until it has finished.
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

This is explained thoroughly in MSDN:
If result is non-zero (which means that it succeeded) you will get the handle and processid in the pi structure.
In order to kill the process you can use TerminateProcess

Related

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.

Start a process not as a child

I need to start a process and run it as a detached process. I have some sort of starter application which purpose is to run another exe and immediately exit. What is a best way to achieve that?
I read CreateProcess documentation several times but still have questions. Documentation says that I need to call CloseHandle after I finish. But my parent app shouldn't wait for a child to exit. Another part of documentation says that I can leave handles alone - the system will close them when the parent process terminates. Does that means that child application exits immediately after parent? It seems not true - I close a starter but my child process still runs.
There's a DETACHED_PROCESS flag that seem what I'm looking for. But documentation says something about console. What console? I don't care about console.
DETACHED_PROCESS flag documentation states
For console processes, the new process does not inherit its parent's console (the default)
that means: if you have a console process and you start a new one, it will not inherit its parent's console.
If you don't have a console process you don't have to worry about it.
CreateProcess creates a child process but does not wait for the child process to finish, so you're already all set.
If you wanted to wait for the child process to complete, you should have called CreateProcess and then WaitForSingleObject
To summarize:
// Version 1) Launch and wait for a child process completion
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
if (CreateProcess(L"C:\\myapp.exe", L"", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo)) {
::WaitForSingleObject(processInfo.hProcess, INFINITE); // DO WAIT for the child to exit
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
// ----------------------------------------------------------------
// Version 2) Launch and do NOT wait for a child process completion
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
if (CreateProcess(L"C:\\myapp.exe", L"", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo)) {
CloseHandle(processInfo.hProcess); // Cleanup since you don't need this
CloseHandle(processInfo.hThread); // Cleanup since you don't need this
}
notice that version 2 will not terminate your child process. Only resources which are no longer needed will be released.
I read CreateProcess documentation several times but still have questions. Documentation says that I need to call CloseHandle after I finish. But my parent app shouldn't wait for a child to exit.
Okay, then don't wait. You can call CloseHandle immediately in the parent.
Another part of documentation says that I can leave handles alone - the system will close them when the parent process terminates. Does that means that child application exits immediately after parent? It seems not true - I close a starter but my child process still runs.
No, it doesn't. I'm not sure how you got that from the documentation, but that's not what it means.
There's a DETACHED_PROCESS flag that seem what I'm looking for. But documentation says something about console. What console? I don't care about console.
If you don't care, then don't worry about it.

having a HANDLE to a Process how to sign up for monitoring of its close/restart/duplication event?

Having a handle tpo a process like so:
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
How to sign up for this process update events - like close\restart? Is it possible to sign up for duplication event (start up of second same process)?
Process handles are signaled when the process they represent exits. So to find out when the process exits, you can pass hProcess to WaitForSingleObject or any other wait function.

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.

Win32 windowless application - wait for program exit

I have a windowless application whose only purpose is to install a 32 bit hook DLL file and wait until the parent program (a 64-bit program) exits. The 64-bit program is written in C#, and the windowless application is written in C++. I originally had this GetMessage loop which held the program open:
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
I was closing the C++ application using the Process.Kill method in C#, but I found out that that isn't allowing the C++ application to close cleanly. Also, if the C# application crashed, the C++ application would stay open forever. I made the C++ application check to see if the C# application is still running, using this loop:
while(true)
{
if(PeekMessage(&msg, NULL, 0, 0, true))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(!isMainProgramRunning())
break;
Sleep(1000);
}
For some reason the Sleep causes problems. The hooks installed by the DLL file are WH_CBT and WH_KEYBOARD. Whenever I press a key while the C++ application is running with this loop, the keys just get eaten up. Removing the Sleep makes it work fine, but, as expected, it uses 100% CPU, which I don't want. I tried removing the message loop altogether and instead using WaitForSingleObject with an infinite timeout on a thread which would end when isMainProgramRunning returned false. This basically locks up the whole computer.
I don't really understand why GetMessage, which, as far as I saw, never returned, but suspended the main thread indefinitely, didn't cause these problems yet WaitForSingleObject causes every application to freeze when I click on it. How can I get the C++ application to stay open until the C# application closes?
Edit:
Since it's been pointed out to me that sleeping in a message pump is bad, let me ask this: Is there a way to specify a timeout on the message waiting, so the program isn't waiting indefinitely for a message, but rather, will wait about 250 ms, timeout, let me run the isMainProgramRunning method, then wait some more?
Edit2:
I tried using MsgWaitForMultipleObjects, although in a somewhat different way than Leo suggested. This is the loop I used:
while(MsgWaitForMultipleObjects (0, NULL, true, 250, QS_ALLPOSTMESSAGE) != WAIT_FAILED)
{
if(PeekMessage(&msg, NULL, 0, 0, true))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(!isMainProgramRunning())
break;
}
Again I had the same problem with the Sleep. I also tried suspending the main thread and having the other thread resume it. Same problem. What is it that GetMessage does that allows it to wait without causing these problems? Maybe this should be the subject of another post, but why is it that when the C++ application installing the hooks sleeps or is suspended, all processing in the hooks seems to suspend as well?
Edit3:
Here is the DLL method that the C++ application calls to install the hooks:
extern "C" __declspec(dllexport) void install()
{
cbtHook = SetWindowsHookEx(WH_CBT, hookWindowEvents, hinst, NULL);
if(cbtHook == NULL)
MessageBox(NULL, "Unable to install CBT hook", "Error!", MB_OK);
keyHook = SetWindowsHookEx(WH_KEYBOARD, LowLevelKeyboardProc, hinst, NULL);
if(keyHook == NULL)
MessageBox(NULL, "Unable to install key hook", "Error!", MB_OK);
}
You have two separate problems:
How to make the windowless C++ program exit automatically if the C# program exits (e.g. crashes).
In the C++ program, open a handle to the C# program. Since the C# program runs the C++ program, have the C# program pass its own PID as an argument; the C++ program can then open a handle to that process using OpenProcess.
Then use MsgWaitForMultipleObjects in your message loop. If the C# program exits the handle you have to it will be signalled and you will wake up. (You can also use WaitForSingleObject(hProcess,0)==WAIT_OBJECT_0 to check if the process is signalled or not, e.g. to verify why you were woken up, although the MsgWaitForMultipleObjects result will tell you that as well.)
You should close the process handle as you are exiting (although the OS will do it for you when you exit, it's good practice in case you re-use this code in a different context). Note that the handle outlives the process it represents, and that is why you can wait on it.
How to make the C# program instruct the C++ program to exit.
You may not need this if you get #1 working, but you could just have the C# program post a message to the C++ one if you want.
Do NOT use PostQuitMessage and do NOT post or send WM_QUIT across threads or processes.
Instead, post some other message that the two apps agree on (e.g. WM_APP+1) using PostThreadMessage.
You can create a named event and use:
MsgWaitForMultipleObjects
in your message loop.
The C# application only have to open and raise this event to tell your application to exit.
It's kind of minimal interprocess communication.
You should exit the process by posting a WM_QUIT message to it and handling it correctly, as specified in this article (Modality), by Raymond Chen. Don't sleep inside a loop without handling messages - it's wrong. Your app should either be handling a message or waiting for new messages.
GetMessage never returns is because you don't have a window created!
To use a message-queue you have to have some GUI. You Can for instance create a hidden window.