From: Julian Mensch on
> I think you can use AttachConsole something like this:

Thank you so much; I think this might be what I'm looking
for, though I still have to test it. I appreciate the help!

-- Julian Mensch
From: Julian Mensch on
Thanks for the code link. I've already god a kludge vaguely like
this (call from small exe, write output to file, have small exe dump
file to stdout), but this is more elegant by far, and I'll use it if I
can't get the AttachConsole method below to work. Again, I
appreciate the effort everyone took to answer my question so
quickly. :)

-- Julian Mensch
From: m on
IIRC, the only special attribute of a console app is that it inherits a
console from its parent (standard IOE); or has one created and associated
automatically by CSRSS. It, or any other process on Windows can create any
number of consoles or windows and use them as it sees fit - of course one
should follow the MS user experience guidelines ;)

"Julian Mensch" <jmensch(a)shaw.ca> wrote in message
news:98576c42-462b-4a73-9b86-7b65daa921f5(a)d9g2000prh.googlegroups.com...
> I hope I have the right group for this; I think so, because
> it's fundamentally about Win32 API calls.
>
> I currently have a large C++ application which, on startup,
> launches a GUI using the third-party Allegro graphics library.
> To work correctly doing this, I understand it need to be a
> Windows Application, not a Console Application. There's a
> few assorted reasons it needs to be a WinApp, anyway.
>
> However, it also has a secondary use as a development
> tool, for which I would like to support a command-line
> interface. I would think this wouldn't be a problem, since
> I can just bypass starting my graphics library and use the
> standard C++ libraries like cout or printf() -- but of course I
> can't, because it's a Windows Application and to support its
> main functionality can't be made into a Console Application.
> Essentially, it needs to decide right on startup whether it is
> going to behave like a Windows Application or a Console
> Application, based on argc/argv command-line parameters.
>
> Note that since this is a command-line development tool,
> it's not good enough for it to spawn a console window and
> write to that -- it has to be able to deal with output being
> redirected so that, for example, if it is run from an IDE like
> Visual Studio to compile some script code, the error messages
> get redirected correctly to VS's Output pane, or if I run it
> from cmd.exe like so:
>
> mytool.exe -c myscript.is > output.txt
>
> All the output goes to a text file rather than the screen. Is
> it even possible to do this with a Windows Application, and
> if so can someone tell me which API calls I need to research
> in order to achieve it?
>
> Thanks graciously for any help anyone can provide here!

From: Tim Roberts on
"m" <m(a)b.c> wrote:

>IIRC, the only special attribute of a console app is that it inherits a
>console from its parent (standard IOE); or has one created and associated
>automatically by CSRSS. It, or any other process on Windows can create any
>number of consoles or windows and use them as it sees fit

This is absolutely correct. A console app can create windows and jump into
a message loop.
--
Tim Roberts, timr(a)probo.com
Providenza & Boekelheide, Inc.
From: Julian Mensch on
Okay, so I now have the ideal solution to this issue for my
needs. 80% of it was in David's post (thanks!), but the trick
is to call GetStdHandle *before* AttachConsole/AllocConsole
because the latter two functions will overwrite handles resulting
from pipes and other IO redirection.

In case anyone else has the same issue and decides to
Google here, I'll share my code; AFAIK this makes a Windows
app work like a command line tool regardless of whether it was
started from GUI, cmd.exe and even sends output to the VS
Output pane correctly.

-----------

FILE *consoleDump;

int CommandLineCompile(const char *fileName, int32 CompileFlags)
{
bool newConsole = false;
/* Case 1: We spawn with stdout redirected as the result of a
command line pipe ("incursion -c test.is > errors.txt") or
the similar redirection of the VS Output pane. */
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut != 0 && hStdOut != INVALID_HANDLE_VALUE)
goto InPipeOK;

/* Case 2: We spawn from a command prompt without redirection,
and thus want to send output to the existing console created
by cmd.exe or a similar app. */
bool gotConsole = AttachConsole( ATTACH_PARENT_PROCESS );
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdOut == INVALID_HANDLE_VALUE)
exit(1);

/* Case 3: We spawn from Windows GUI, so there's no existing
console and we need to create one. */
if (!gotConsole && hStdOut == 0) {
gotConsole = AllocConsole();
if (!gotConsole)
exit(1);
newConsole = true;
hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
}

InPipeOK:
int hCrt = _open_osfhandle((intptr_t)hStdOut,_O_TEXT);
consoleDump = _fdopen( hCrt, "w" );
*stdout = *consoleDump;
int i = setvbuf( stdout, NULL, _IONBF, 0 );
if (!consoleDump)
exit(1);
fprintf(consoleDump,"IncursionScript Resource Compiler\n");
theComp = new ISCompiler();
bool ok = theComp->Compile(fileName,true);
delete theComp;

/* Ask for a keypress only if we created a new console, so
that it doesn't flash up and then disappear again before
the user can read messages, but don't ask if io is redirected
or if we launch from command prompt because that would
mess up BAT files and other batch processes. */
if (newConsole) {
fprintf(consoleDump,"\nPress [ENTER] to continue...");
fflush(consoleDump);
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
if (hStdIn == INVALID_HANDLE_VALUE)
goto Terminate;
char buff[1024]; DWORD bytesRead;
ReadFile(hStdIn,buff,1,&bytesRead,NULL);
}
Terminate:
fflush(consoleDump);
exit(ok != true);
}