32

Can I display the result of a loop in the console window in a VCL application for debugging purposes?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
emurad
  • 3,448
  • 10
  • 40
  • 47

4 Answers4

35

The simplest way is to compile as a console application, but put the normal application framework code back in the dpr.

program Project2;

{$APPTYPE CONSOLE}

uses
  Forms,
  SysUtils,
  Unit1 in 'Unit1.pas' {Form1};

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  writeln('Hello, World!');
  Application.Run;
end.

A slightly more complex way is to use the Windows API AllocConsole call:

program Project2;

uses
  Forms,
  SysUtils,
  Windows,
  Unit1 in 'Unit1.pas' {Form1};

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  AllocConsole;
  writeln('Hello, World!');
  Application.Run;
end.

This method has the (usually) disadvantage of creating a new console if you are calling from the command line. From memory getting redirection to work requires some more code as well. The advantage is that you can decide to allocate the console at run-time, rather than compile time.

Gerry Coll
  • 5,867
  • 1
  • 27
  • 36
  • I think these behave differently if you call the program from the console. The first attaches to the existing console window, the second creates a new one. – CodesInChaos Dec 12 '10 at 10:34
  • Attaching to the first console is usually more desirable – David Heffernan Dec 12 '10 at 14:22
  • @CodeInChaos, @David - yeah, I forgot to mention that. It is also a pain if you want to redirect input or output. Its big advantage is that it can be done optionally in a project, which can be useful for debugging. – Gerry Coll Dec 12 '10 at 23:56
35

In Windows, the simplest way to output debug information is to use OutputDebugString() and then use an application able to receive that output. The event viewer in the Delphi IDE itself is able to receive that input, or you can use the DebugView application from SysInternals to get output on a system that hasn't the IDE installed. AFAIK, GExperts has a similar tool too. That's because a GUI application has not by default a console where to write output, otherwise you have to create one (see Gerry's answer).

One of OutputDebugString()'s advantages is that the application will work without problems even if a call slips into a release build (or is if left there intentionally), but be careful then to not output sensitive information, because they can be read using one of the tools above.

You could also create an ad-hoc form (that is, with a memo control) and route output there.

There are also advanced logging facilities like SmartInspect, CodeSite and others.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 8
    FWIW, I want to mention that this does not answer the question, which is *"How can I write to* **console window** *for debugging?"* – Sertac Akyuz Dec 13 '10 at 10:43
  • 1
    Maybe because in Windows writing to a console is not the best way to debug? Windows is not Linux or Java. –  Dec 13 '10 at 15:44
  • OutputDebugString() is definitely the "simplest". When you need "robust", though, it's better to DIY with a console window. Do a Google search for "We have seen problems for years with OutputDebugString() being unreliable at times" for why "simplest" and "robust" are not the same. If it doesn't absolutely have to work every single time, OutputDebugString() is fine. – Ron Burk Oct 02 '13 at 06:46
13

Delphi has got an option for this, check "Generate console application" in the linker options for the project. Standard I/O will be directed to a console window which will accompany your GUI application. Then you can use Writeln etc. as you normally would.

Read Output (or Input) from the docs:

Delphi programs have a standard output file if they are linked as console applications.

Sertac Akyuz
  • 54,131
  • 4
  • 102
  • 169
  • Setting "generate console application" will mark the PE executable as a console application. See here for some issues when mixing executable types: http://blogs.msdn.com/b/junfeng/archive/2004/02/06/68531.aspx –  Dec 12 '10 at 21:53
  • @ldsandon - I read the blog entry and couldn't find the issues you mention. Can you make a quote here?.. FWIW the option is there since *Delphi 2* and I've never came across a QC report or complaint or issue regarding the option. The option's sole purpose is to provide standard I/O to a GUI application. Further reading: [Standard Routines and I/O](http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/standardroutinesov_xml.html) – Sertac Akyuz Dec 12 '10 at 23:16
  • The option's sole purpose it to mark the executable as a console application in the PE header. See for example "Here is what the author of ildasm says" about what can happen when you do that. –  Dec 13 '10 at 08:35
  • @ldsandon - That's what the option does, I thought it was done for a **reason**... I've read the comment you mentioned before. AFAICS, Delphi's linker option exhibits *none* of the glitches he mentions: *"Doesn't release console window when launched from..."* should it? *"Can't redirect console dump to a file..."* Delphi has got no problem with it, *Assign* a file and output is redirected just fine. *"Momentarily flashes a console window..."* Nope, not in Delphi... – Sertac Akyuz Dec 13 '10 at 10:38
  • Read better what was written there: not all those effects were due to the console application type. Some happens when you allocate a console from a GUI app, others if you use a console app to display a GUI. Unless Delphi uses a fake console app (I think it does not), what happens is not under the control of the VCL, but of Windows itself. If the code is C, C++ or Delphi doesn't matter. –  Dec 13 '10 at 15:55
  • @ldsandon - Never told the code would matter.. I tested as far as I could, and couldn't find any negative aspect of the option. If you know one, just say it. – Sertac Akyuz Dec 13 '10 at 16:10
  • If the sole purpose is for debugging, there is no great problem in using this approach (or AllocConsole) as long as it is removed afterwards (e.g. using conditional define). It doesn't have to be perfect! I seem to recall using AllocConsole in the past for an importer application, but can't remember if it was production or proof-of-concept code. – Gerry Coll Dec 14 '10 at 03:23
  • @Gerry - I can't think of a purpose other than debugging. Being able to put 'AllocConsole' in a '{$IFDEF DEBUG}' is one distinct advantage over this one (the reason I've upvoted), but for a quick test app checking the linker option is quick (I'd guess the reason for your upvote :) ). – Sertac Akyuz Dec 14 '10 at 10:38
  • The "negative aspects" are in the eye of the beholder. To me an application that doesn't release a console or can be closed closing a console has negative aspects. If it is a debugging solution may be ok, still I believe there are better debugging facilities. For example OutputDebugString is thread safe, if you're using a console you have to protect concurrent accesses yourself. –  Dec 14 '10 at 14:21
1

If you wrote the console application, you can try OutputDebugString function in the console application (I didn't try).

Or you can capture the output of the console application like in Capture the output from a DOS (command/console) Window .

Also, you can check Console Application Runner Classes. I use these classes. I think they are great.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
SimaWB
  • 9,246
  • 2
  • 41
  • 46