I have a common unit that does some logging to GExperts Debugger and/or OutputDebugString. I am going to use it in a console app, so I want it to be able to output to stdout via writeln()
.
- the main console app, which will link to a BPL,
- from another BPL that "requires" the first bpl, and.....
- from a DLL that statically links the unit.
The BPLs and DLL will be built with no visibility to the {$APPTYPE CONSOLE} directive, so I can't use IFDEF conditional compilation. The BPL and DLL need to be able to go either way, depending whether the main app is a regular winapp or console app.
One ugly solution that occurred to me is to use the name of the executable. ex:
if (UpperCase(ExtractFileName(ParamStr(0))) = 'MYCONSOLEAPP.EXE') then ...
But I hate to do that, as I could have other console apps...
I'd rather just have a magic function AmIAConsoleApp : boolean; Is there anything like that? I'm using Delphi2005 on this project.
Update: I see that I'm kind of a duplicate of this question, but I'd like to survey the Delphi folks to see if there's a better approach.
Call GetStdHandle(Std_Output_Handle)
. If it succeeds and returns zero, then there is no console to write to. Other return values indicate that a console is attached to the process, so you can write to it (although the console may not be the most desirable place to log messages in a console program since they'll interfere with the normal output). Something like this:
function IAmAConsoleApp: Boolean;
var
Stdout: THandle;
begin
Stdout := GetStdHandle(Std_Output_Handle);
Win32Check(Stdout <> Invalid_Handle_Value);
Result := Stdout <> 0;
end;
Use constructor injection to inject a logger at the time you create the instance. Here's a simple example.
Your proposed solution of testing whether the app is a console app works for only those two scenarios. The constructor injection solution is scarcely any more code and works anywhere you need output.
精彩评论