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

Killing a console application nicely

1,076 views
Skip to first unread message

Gerald Nunn

unread,
Jan 25, 2002, 10:00:23 AM1/25/02
to
I'm starting a console app (java application server) using CreateProcess and
capturing it's output which is then redirected to a Delphi GUI. What is the
best way to kill the app nicely? I can use TerminateProcess but this is an
abrupt termination that results in the app thinking it has crashed and
performing a variety of checks the next time it starts up. I can't send a
WM_CLOSE or WM_QUIT message since it doesn't have a window. I tried
GenerateConsoleCtrlEvent to send a CTRL-C or a CTRL-Break but no luck there
either. Any ideas?

Thanks,

Gerald


Michael Winter

unread,
Jan 25, 2002, 5:30:35 PM1/25/02
to
Gerald Nunn schrieb:

>
> I'm starting a console app (java application server) using CreateProcess and
> capturing it's output which is then redirected to a Delphi GUI. What is the
> best way to kill the app nicely?

If you really run it in a console window, how do you terminate it? Type
something like 'exit'?

In that case, write that into the stdin of the redirected console.

-Michael
--
No private e-mails please unless explicitly invited.

Gerald Nunn

unread,
Jan 25, 2002, 9:36:17 PM1/25/02
to

"Michael Winter" <delph...@gmx.net> wrote in message
news:3c51dcee$1_1@dnews...

> If you really run it in a console window, how do you terminate it? Type
> something like 'exit'?

Ah, if it was only that easy, it's Oracle 9iAS that I am running in a
command line. When you run it in the normal command prompt, clicking the
close button seems to close it normally. However, if I run it using
createprocess and terminateprocess, next time it starts up it complains
about abnormal termination, which is what I would expect after using
TerminateProcess on it. I just don't see any other way to kill the process
normally.

> In that case, write that into the stdin of the redirected console.

I would, but it doesn't take any input.

Gerald


Grinder

unread,
Jan 25, 2002, 11:32:09 PM1/25/02
to

"Gerald Nunn" <gn...@workbrain.com> wrote in message
news:3c521649_1@dnews...

I've found some discussion of SafeTerminateProcess, a function
that does as you intend. I found this C implementation, but
can't vouch for it:

BOOL SafeTerminateProcess(HANDLE hProcess, UINT uExitCode)
{
DWORD dwTID, dwCode, dwErr = 0;
HANDLE hProcessDup = INVALID_HANDLE_VALUE;
HANDLE hRT = NULL;
HINSTANCE hKernel = GetModuleHandle("Kernel32");
BOOL bSuccess = FALSE;

BOOL bDup = DuplicateHandle(GetCurrentProcess(),
hProcess,
GetCurrentProcess(),
&hProcessDup,
PROCESS_ALL_ACCESS,
FALSE,
0);

// Detect the special case where the process is
// already dead...
if ( GetExitCodeProcess((bDup) ? hProcessDup : hProcess,
&dwCode) &&
(dwCode == STILL_ACTIVE) )
{
FARPROC pfnExitProc;

pfnExitProc = GetProcAddress(hKernel, "ExitProcess");

hRT = CreateRemoteThread((bDup) ? hProcessDup :
hProcess,
NULL,
0,

(LPTHREAD_START_ROUTINE)pfnExitProc,
(PVOID)uExitCode, 0, &dwTID);

if ( hRT == NULL )
dwErr = GetLastError();
}
else
{
dwErr = ERROR_PROCESS_ABORTED;
}


if ( hRT )
{
// Must wait process to terminate to
// guarantee that it has exited...
WaitForSingleObject((bDup) ? hProcessDup : hProcess,
INFINITE);

CloseHandle(hRT);
bSuccess = TRUE;
}

if ( bDup )
CloseHandle(hProcessDup);

if ( !bSuccess )
SetLastError(dwErr);

return bSuccess;
}
/* End of File */

Grinder

unread,
Jan 26, 2002, 12:33:37 AM1/26/02
to
I tried the simple program below to see if I could convert the C
code posted earlier. It visible works for wordpad and mspaint,
but there will surely be security and application issues in this
approach. (I have administrative rights, and the target
programs don't profess themselves to be "unbreakable.")

I hope this at least gives you a starting point. I would be
interested (if you try this) how it works out for you.

_______________

program safeexitproc;
{$APPTYPE CONSOLE}
uses
SysUtils,
Windows;

function SafeTerminateProcess(const hProcess: Cardinal; var
uExitCode: Cardinal): Boolean;
var
iExitCode: Cardinal;
hThread: Cardinal;
iThreadId: Cardinal;
hKernel: HMODULE;
pExitProc: TFarProc;
begin
// be optimistic -- True means the process is terminated
Result := True;

if not GetExitCodeProcess(hProcess, iExitCode) then
// could not get an exit code--something is wrong
Result := False
else if iExitCode <> STILL_ACTIVE then
// process as already terminated
uExitCode := iExitCode
else begin
// get a pointer to ExitProcess


hKernel := GetModuleHandle('Kernel32');

pExitProc := GetProcAddress(hKernel, 'ExitProcess');

// create a remote thread in that process
Result := False;
hThread := CreateRemoteThread(hProcess, nil, 0, pExitProc,
Pointer(uExitCode), 0, iThreadId);

if hThread <> 0 then begin
WaitForSingleObject(hProcess, INFINITE);
CloseHandle(hThread);
Result := True;
end;
end;
end;

var
sApp: string;
rSI: TStartupInfo;
rPI: TProcessInformation;
iEC: Cardinal;

begin
sApp := 'C:\winnt\system32\mspaint.exe';
sApp := 'C:\program files\windows nt\accessories\wordpad.exe';

FillChar(rSI, sizeof(TStartupInfo), #0);
FillChar(rPI, sizeof(TProcessInformation), #0);
rSI.cb := sizeof(TStartupInfo);

if CreateProcess(PChar(sApp), nil, nil, nil, False,
CREATE_NEW_PROCESS_GROUP + NORMAL_PRIORITY_CLASS, nil, nil, rSI,
rPI) then begin
ReadLn;

iEC := 0;
if SafeTerminateProcess(rPI.hProcess, iEC) then
WriteLn('Process terminated')
else begin
WriteLn('Process could not be terminated')
end;

CloseHandle(rPI.hThread);
CloseHandle(rPI.hProcess);
end;
end.


Gerald Nunn

unread,
Jan 26, 2002, 12:39:30 AM1/26/02
to
Thanks, very much. I'll give this a go tomorrow and post some results here.

Gerald


Grinder

unread,
Jan 26, 2002, 12:45:35 AM1/26/02
to

"Gerald Nunn" <gn...@workbrain.com> wrote in message
news:3c524139$1_1@dnews...

> Thanks, very much. I'll give this a go tomorrow and post some
results here.

I didn't think to do it in time, but instead of:

function SafeTerminateProcess(const hProcess: Cardinal; var
uExitCode: Cardinal): Boolean;

it should be:

function KillingMeSoftly(const hProcess: Cardinal; var
uExitCode: Cardinal): Boolean;

Grinder

unread,
Jan 26, 2002, 2:03:54 AM1/26/02
to

"Gerald Nunn" <gn...@workbrain.com> wrote in message
news:3c524139$1_1@dnews...
> Thanks, very much. I'll give this a go tomorrow and post some
results here.

I found something that sounds better (because it does more) than
what I'm doing:

http://www.pcmag.com/print_article/0,3048,a%253D13656,00.asp


Michael Winter

unread,
Jan 26, 2002, 4:46:54 PM1/26/02
to
Gerald Nunn schrieb:

> > If you really run it in a console window, how do you terminate it? Type
> > something like 'exit'?
>
> Ah, if it was only that easy, it's Oracle 9iAS that I am running in a
> command line. When you run it in the normal command prompt, clicking the
> close button seems to close it normally.

Hmm. Strange. No complaints from Windows that the applications is not
ended yet?

Does anyone know how Windows would try to terminate a console
applictaion if you close the console window? Sending ^C or ^Break?

> However, if I run it using
> createprocess and terminateprocess, next time it starts up it complains
> about abnormal termination, which is what I would expect after using
> TerminateProcess on it. I just don't see any other way to kill the process
> normally.

Another idea would be to CreateRemoteThread a thread inside the console
application, and executing ExitProcess there.

Gerald Nunn

unread,
Jan 26, 2002, 9:19:35 PM1/26/02
to

"Michael Winter" <delph...@gmx.net> wrote in message
news:3c5325d2_2@dnews...

> Hmm. Strange. No complaints from Windows that the applications is not
> ended yet?

Nope, it just shuts down normally.

> Does anyone know how Windows would try to terminate a console
> applictaion if you close the console window? Sending ^C or ^Break?

There is GenerateConsoleCtrlEvent which I have tried with no success

> Another idea would be to CreateRemoteThread a thread inside the console
> application, and executing ExitProcess there.

Unfortunately it's not an application I have control over but a commercial
java application server.

Thanks,

Gerald


Gerald Nunn

unread,
Jan 26, 2002, 10:52:59 PM1/26/02
to
This seems to work well at home on my own PC using a command prompt, I'll
try it at work on monday with Oracle 9iAS and see what happens. Seems
promising though, thanks again very much.

Gerald


Manuel Algora

unread,
Jan 27, 2002, 4:58:59 AM1/27/02
to
On Sat, 26 Jan 2002 01:03:54 -0600, "Grinder"
<gri...@no.spam.maam.com> wrote:

>I found something that sounds better (because it does more) than
>what I'm doing:
>
>http://www.pcmag.com/print_article/0,3048,a%253D13656,00.asp

I could not find a link to download the program on that page. Did you
find it?

Manuel Algora
cen...@wanadoo.es

DGJ

unread,
Jan 27, 2002, 7:45:16 AM1/27/02
to

Hi, try this

http://common.ziffdavisinternet.com/download/0/1216/EndItAll2.zip

On Sun, 27 Jan 2002 10:58:59 +0100, Manuel Algora <cen...@wanadoo.es>
wrote:

Michael Winter

unread,
Jan 27, 2002, 1:13:39 PM1/27/02
to
Gerald Nunn schrieb:

> > Another idea would be to CreateRemoteThread a thread inside the console
> > application, and executing ExitProcess there.
>
> Unfortunately it's not an application I have control over but a commercial
> java application server.

With CreateRemoteThread you can 'inject' a thread into another
application.

Gerald Nunn

unread,
Jan 27, 2002, 2:25:52 PM1/27/02
to

"Michael Winter" <delph...@gmx.net> wrote in message
news:3c544554_1@dnews...

> With CreateRemoteThread you can 'inject' a thread into another
> application.

Yep and this essentially is what the code Grinder posted does. It seems to
work well enough at home with the c prompt, I'll give it a whirl tomorrow
with the app server and see how it goes.

Gerald


Marcel van Brakel

unread,
Jan 27, 2002, 6:06:49 PM1/27/02
to
> Yep and this essentially is what the code Grinder posted does. It seems to
> work well enough at home with the c prompt, I'll give it a whirl tomorrow
> with the app server and see how it goes.

Maybe stating the obvious here but didn't see it mentioned yet, calling
ExitProcess in this manner indeed provides a much cleaner exit then
TerminateProcess (and thus should be preferred) but it is far from a true
clean exit. Depending on what the process is doing it might still cause data
corruption and who knows what. Just a warning...

best regards,
Marcel van Brakel


Manuel Algora

unread,
Jan 28, 2002, 7:26:12 AM1/28/02
to
On Sun, 27 Jan 2002 12:45:16 +0000, DGJ <D...@No.Spam-BTINTERNET.com>
wrote:

Thanks!

Manuel Algora
cen...@wanadoo.es

Grinder

unread,
Jan 27, 2002, 4:36:28 PM1/27/02
to
> I could not find a link to download the program on that page.
Did you
> find it?

Try this one:

http://www.pcmag.com/article/0,2997,s%253D1478%2526a%253D13909,0
0.asp


0 new messages