🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.nativeapi
Article #6934

Console stays open after redirected CreateProcess.

#6934
From: Bob Gonder
Date: Thu, 24 Mar 2005 20:04
158 lines
5743 bytes
XP-Home sp2,  BCB 5.5

Trying to get my Server app to execute a DOS app and redirect the
output to the Client.

This works, but later, when the Server closes, it's console stays
open.  If the Client doesn't request this particular service before
closing, the console goes away just fine.

Task Manager Process entry for the program goes away like it should.
The Application tab still shows the program.
The Performance tab increases Handles, Threads, Processes for each
execution until the windows are manually closed.
Handles reduce with each closed window, but remain higher than
pre-execution. (Am I missing some Handle Closes?)

Eventually, I'd like to do away with the Server's console, but the
redirection doesn't seem to work at all without one.

So, Two Questions: (L and N in the truth table below)
1) Why does the console remain after program shutdown (and how to
close it).
2) Why doesn't redirection work without a Console (WithConsole==0)?
3) Am I missing some Handle Closes?

(I added > to every line to defeat word wrapping. The code contains no
'>', so you can do a global delete to clean them up.)

 - - redirect.c
>#include "windows.h"
>#pragma	hdrstop
>
>// Change these 3 settings
>#define		WithConsole	1
>#define		Run		1
>#define		Redirect		1
>/*
>		Redirect 0	Redirect 1
>		Run1	Run0	Run1
>	Cons1	L	Ok	L	
>	Cons0	Ok	Ok	N
>L == Console remains after termination.
>N == No "(Redirect)Data" Trace
>*/
>#if		WithConsole
>	DWORD	TraceBytesWritten;
>#define		Trace(x)	WriteFile( stdout,x,lstrlen(x),&TraceBytesWritten,NULL);
>#else
>#define		Trace(x)	OutputDebugString(x);
>#endif
>
>HANDLE	stdout,stdin;
>HANDLE	MainThreadHandle;	// handle to main() thread
>DWORD	MainThreadID;		// id to main() thread
>
>DWORD _stdcall run_program( char*command )
>{	DWORD ExitCode=0;
>	STARTUPINFO si={0};
>	PROCESS_INFORMATION pi={0};
>#if	Redirect
>	char	buf[128];
>	DWORD	BytesRead;
>	HANDLE	hStdinRd, hStdinWr, hStdoutRd, hStdoutWr; 
>	SECURITY_ATTRIBUTES	saAttr;
>
>	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
>	saAttr.bInheritHandle = TRUE; 
>	saAttr.lpSecurityDescriptor = NULL;
>	CreatePipe(&hStdoutRd, &hStdoutWr, &saAttr, 0);
>	CreatePipe(&hStdinRd, &hStdinWr, &saAttr, 0);
>	si.hStdInput = hStdinRd;
>	si.hStdOutput = hStdoutWr;
>	si.hStdError = hStdoutWr;
>#else
>	si.hStdInput = stdin;
>	si.hStdOutput = stdout;
>	si.hStdError = stdout;
>#endif
>	si.cb = sizeof(si);
>	si.dwFlags = STARTF_USESTDHANDLES;
>
>	if( CreateProcess( 0, command, 0, 0, TRUE, 0, 0, 0, &si, &pi) )
>	{
>		Trace("\n(Run)Accepted");
>		WaitForSingleObject( pi.hProcess, INFINITE );
>		GetExitCodeProcess( pi.hProcess, &ExitCode );
>		Trace("\n(Run)Completed");
>		CloseHandle( pi.hProcess );
>		CloseHandle( pi.hThread );
>	}else{
>		ExitCode = GetLastError();
>		Trace("\n(Run)Aborted");
>	};
>#if	Redirect
>	CloseHandle( hStdoutWr );
>	CloseHandle( hStdinWr );
>	do{
>		Trace("\n(Redirect)CheckingData\n");
>		ReadFile( hStdoutRd, buf, sizeof(buf)-1, &BytesRead, NULL );
>		if( BytesRead )
>		{	Trace("\n(Redirect)Data\n");
>			buf[BytesRead] = 0;
>#if	WithConsole
>			OutputDebugString(buf);//verify debugstring works
>#endif
>			Trace(buf);
>		};
>	}while( BytesRead );
>	CloseHandle( hStdoutRd );
>	CloseHandle( hStdinRd );
>#endif
>	return ExitCode;
>}
>
>#pragma	argsused
>unsigned long _stdcall smain(void*x)	/* thread wrapper for main() */
>{
>#if	Run
>	run_program( "PKZIP.EXE bak.zip *.bak" );
>#else
>	run_program( "PKZaP.EXE bak.zip *.bak" );
>#endif
>	Trace("\n(Main)Completed");
>	return 0;
>}
>
>#pragma argsused
>int _stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
>{	MSG		msg = {0};	// message
>#if	WithConsole
>	AllocConsole();
>#endif
>	stdin  = GetStdHandle(STD_INPUT_HANDLE);	/*Standard input handle*/
>	stdout = GetStdHandle(STD_OUTPUT_HANDLE);
>
>	if( 0!=(MainThreadHandle = CreateThread( NULL,0, smain, NULL,0, &MainThreadID)) )
>	{
>		Trace("\n(Win)BeginMessageLoop");
>
>// CreateWindow and Message loop replaced to simplify
>		WaitForSingleObject( MainThreadHandle, INFINITE );
>
>		Trace("\n(Win)EndMessageLoop");
>		CloseHandle( MainThreadHandle );
>	};
>	Trace("\n(Win)Leaving WinMain");
>#if	WithConsole
>	FreeConsole();	// no difference
>#endif
>	return msg.wParam;	// Returns the value from PostQuitMessage
>}

 - - Compilation switches
>CC = $(binpath)\bcc32 -6 -a1 -C -d -g50 -K -O2 -Oi -Os -Ov -Q -VI- -tW  -vi -x- -P -M -v -c -I$(INCLUDEPATH) -L$(LIBPATH)
>TLINK = $(binpath)\ilink32 /aa/v/x/c/C/Gn/P-/Twe/L$(LIBPATH)
>#I can't remember where that /P- or /Twe came from? Removing them, no difference.
>$(TLINK) c0w32.obj+$(FILE).obj, $(FILE), , import32.lib+noeh32+cw32mt.lib
Technical Details
Message-ID: <vi36411dhum1dho5li05dbbsj044qur13j@4ax.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news.maxwell.syr.edu!irazu.switch.ch!switch.ch!news.belwue.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail

Show Full Headers
Complete Article Headers
X-Google-Thread: 10cc67,3a2a64440564cd69,start
X-Google-Attributes: gid10cc67,public
X-Google-Language: ENGLISH,ASCII-7-bit
From: Bob Gonder <notbg@notmindspring.invalid>
Newsgroups: borland.public.cppbuilder.nativeapi
Subject: Console stays open after redirected CreateProcess.
Date: Thu, 24 Mar 2005 12:04:13 -0800
Organization: MindSpring Enterprises, Inc.
Reply-To: notbg@notmindspring.invalid
Message-ID: <vi36411dhum1dho5li05dbbsj044qur13j@4ax.com>
X-Newsreader: Forte Agent 1.93/32.576 English (American)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
NNTP-Posting-Host: 67.77.146.183
X-Trace: newsgroups.borland.com 1111694652 67.77.146.183 (24 Mar 2005 12:04:12 -0800)
Lines: 162
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!news.maxwell.syr.edu!irazu.switch.ch!switch.ch!news.belwue.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail