Thanks,
Gerald
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.
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
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 */
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
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;
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
> > 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.
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
>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
http://common.ziffdavisinternet.com/download/0/1216/EndItAll2.zip
On Sun, 27 Jan 2002 10:58:59 +0100, Manuel Algora <cen...@wanadoo.es>
wrote:
> > 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.
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
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
Thanks!
Manuel Algora
cen...@wanadoo.es
Try this one:
http://www.pcmag.com/article/0,2997,s%253D1478%2526a%253D13909,0
0.asp