Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CreateProcess and TerminateProcess

2,385 views
Skip to first unread message

Guido Franzke

unread,
Jul 21, 2009, 12:21:03 PM7/21/09
to

Hello NG,

I want to kill a process that I created with CreateProces . This is what I
do:

char* szProgramm = "C:\\Windows\\System32\\mspaint.exe";

STARTUPINFO m_si;
PROCESS_INFORMATION m_pi;

BOOL bRet = CreateProcess( NULL, // No module name (use command line).
szProgramm, // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
0, // No creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&m_si, // Pointer to STARTUPINFO structure.
&m_pi ); // Pointer to PROCESS_INFORMATION structure.
if (!bRet)
{
if (m_pi.hProcess) CloseHandle( m_pi.hProcess );
if (m_pi.hThread) CloseHandle( m_pi.hThread );
}
// now MS Paint has started
// ...
// after some time I want to kill MS Paint again:
if (m_pi.hProcess) CloseHandle( m_pi.hProcess );
if (m_pi.hThread) CloseHandle( m_pi.hThread );
if (m_pi.hProcess) TerminateProcess(m_pi.hProcess,0);


But the process is not terminated/killed.
How can I kill the process?

Thanks for help,
Guido


David Lowndes

unread,
Jul 21, 2009, 1:18:39 PM7/21/09
to
> // now MS Paint has started
> // ...
> // after some time I want to kill MS Paint again:
> if (m_pi.hProcess) CloseHandle( m_pi.hProcess );
>...

> if (m_pi.hProcess) TerminateProcess(m_pi.hProcess,0);
>
>But the process is not terminated/killed.
>How can I kill the process?

For one thing, don't close the handle before you use it.

Dave

Brian Muth

unread,
Jul 21, 2009, 2:07:30 PM7/21/09
to
You should bear in mind that this is a bad idea. The parent process should
be signaling the client process that it is time to exit, so that resources
are returned gracefully back to the operating system. TerminateProcess()
should never be used except in the most extraordinary circumstances.

Brian

Joseph M. Newcomer

unread,
Jul 22, 2009, 12:17:09 AM7/22/09
to
See below..

On Tue, 21 Jul 2009 18:21:03 +0200, "Guido Franzke" <guid...@yahoo.de> wrote:

>
>Hello NG,
>
>I want to kill a process that I created with CreateProces . This is what I
>do:
>
> char* szProgramm = "C:\\Windows\\System32\\mspaint.exe";
>
> STARTUPINFO m_si;
> PROCESS_INFORMATION m_pi;
>
> BOOL bRet = CreateProcess( NULL, // No module name (use command line).
> szProgramm, // Command line.
> NULL, // Process handle not inheritable.
> NULL, // Thread handle not inheritable.
> FALSE, // Set handle inheritance to FALSE.
> 0, // No creation flags.
> NULL, // Use parent's environment block.
> NULL, // Use parent's starting directory.
> &m_si, // Pointer to STARTUPINFO structure.
> &m_pi ); // Pointer to PROCESS_INFORMATION structure.
> if (!bRet)
> {
> if (m_pi.hProcess) CloseHandle( m_pi.hProcess );
> if (m_pi.hThread) CloseHandle( m_pi.hThread );

****
So if the createprocess fails, you try to close a handle on an uninitialized variable
whose value is problematic (if it fails, there won't be a handle) and then you just fall
through and execute the code below anyway...?
****


> }
> // now MS Paint has started
> // ...
> // after some time I want to kill MS Paint again:

****
In what way do you magically determine that it is time to close it? This seems to be a
very bad design, in that any program the user can now use should be under control of the
user, who can close it when done, but not under control of the program that launched it,
because it has no idea what the user is doing.
****


> if (m_pi.hProcess) CloseHandle( m_pi.hProcess );
> if (m_pi.hThread) CloseHandle( m_pi.hThread );
> if (m_pi.hProcess) TerminateProcess(m_pi.hProcess,0);

****
Any program that contains a gratuitous TerminateProcess like this is deeply flawed. There
is no reason to call TerminateProcess. It is a mistake. How do you know the user is not
doing something important to the image at that point? TerminateProcess kills the process
dead, right now, right this instant. Ask about saving the work? No. No chance.

The failure mode should be pretty obvious. You carefully CLOSE the handle BEFORE you
attempt to use it! OF COURSE it won't terminate! You naively assume that
TerminateProcess worked, and apparently neglected to actually check the return code to see
if it succeeded, and therefore failed to examine GetLastError, which almost certainly
gives an error like "invalid handle" or "invalid parameter" or "you are a twit for trying
to use a handle you just closed" or something like that. How do you expect to
successfully use the handle? You just closed it!

The correct way to write code that requires knowing if an operation succeeded would be as
shown here:
if(m_pi.hProcess != NULL)
{ /* terminate */
if(!TerminateProcess(m_pi.hProcess, 0))
{ /* termination failed */
DWORD err = ::GetLastError();
... deal with error
} /* termination failed */
} /* terminate */

That said, TerminateProcess is exactly the WRONG way to do this! See the MSDN article on
terminating a process. The correct way is to PostMessage a WM_CLOSE to the main window of
the application (which you can find by searching the top-level windows and finding the
top-level window whose process ID matches the process ID of your child process).
TerminateProcess is the equivalent of those tire-puncturing strips police use to stop a
vehicle. It is destructive. DO NOT use it except in desperation. This is not a
situation in which desperation exists. Therefore, the choice of using TerminateProcess is
a Very Bad Decision. Don't do it.

Have you actually noticed that "enter" key on your keyboard? Putting the if-statement
and the statement it controls on a single line is poor coding practice.

joe
****


>
>
>But the process is not terminated/killed.
>How can I kill the process?
>
>Thanks for help,
>Guido
>

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Guido Franzke

unread,
Jul 22, 2009, 7:55:10 AM7/22/09
to
Thanks for your answers.
Now I don't call CloseHandle, only TerminateProcess. And the programm is
killed the way I want :-)

I'm sorry you only looked on the mspaint.exe programm. Of course it's better
to send WM_CLOSE. But this is only an example for testing. Indeed we buy an
old DOS server programme with an infinite loop, and sometimes this old
programme hangs. So I need to kill the DOS process and restart
automatically.

Thanks for your help.
By the way. Is TerminateProcess safe with memory and thread handling? Do you
know if I will run in trouble with memory allocation etc?

Regards
Guido

Goran

unread,
Jul 22, 2009, 8:50:21 AM7/22/09
to
> Is TerminateProcess safe with memory and thread handling? Do you
> know if I will run in trouble with memory allocation etc?

No problem there. Cleaning up after a dead process is the job of the
OS. God knows that there are many programs that die under Windows so
it has to be able to get them out cleanly - and it does.

If you really have a console app, it seems that you really are really
best off using TerminateProcess. A quick look at Process.Kill in .NET
(with ildasm) may reveal useful info (that is, how MS does that).

Goran.

Joseph M. Newcomer

unread,
Jul 22, 2009, 11:54:01 AM7/22/09
to
If it is an MS-DOS program, the correct solution is again not to call TerminateProcess,
but to use GenerateConsoleCtrlEvent with a Ctrl+C event. Only if that fails should you
call TerminateProcess. This will correctly invoke (the default handler) the AtExit
conditions that will properly close files and do other cleanup.

TerminateProcess should be considered extremely dangerous under all conditions. Note that
when you use the Task Manager to kill a process, it says that terminating a process "may
contribute to system instability". Using TerminateProcess can corrupt your files (what
happened to those unwritten buffers?) whereas GenerateConsoleCtrlEvent will allow for a
gentle close-files-and-write-buffers solution. You should always treat TerminateProcess
as being the equivalent of putting a block of C4 into the Process Execution Block (PEB)
and detonating it, with bits flying everywhere. There is likely to be collateral damage.

Note: if your problem is different than the one you are showing, why are you showing us
something that is unrelated to the problem you are trying to solve?

The reason we looked at the mspaint.exe program is THAT IS THE EXAMPLE YOU GAVE US! If
your example was to fire off a 16-bit MS-DOS program, you must say so. If your example is
to fire off a 32-bit console program, you must say so. If your purpose is to kill a
misbehaving program, you must say so. Do not create a synthetic example unrelated to your
problem and expect us to guess that your problem is something completely different.
joe

Guido Franzke

unread,
Jul 23, 2009, 9:33:32 AM7/23/09
to
Ok, thanks for your response. I check it out.

I'm sorry, I did not tell first that I use a DOS programme. I was not aware
of the importance 'what' programme I want start and kill later, I only
wanted to kill a process. I know now. Please excuse my simplemindedness.
Regards
Guido


Joseph M. Newcomer

unread,
Jul 23, 2009, 2:38:05 PM7/23/09
to
It really makes a difference; note also that you need to make it clear what you mean by
"MS-DOS program", since some people mean "An old 16-bit console app" and others mean "A
modern 32-bit console app". And yes, it makes a BIG difference in the answer if you are
trying to kill a GUI app (the example you gave), a 16-bit console app, or a 32-bit console
app!
joe

0 new messages