0

Is it possible to create Create delphi application which is a GUI or Console application depending on a command or parameter(commands or parameter can be set while executing from command propt)

I have tried as flows but its look like console application even if I pass the parameter or not

if (ParamStr(1) = 'test') then
  begin
    {$APPTYPE CONSOLE}
    WriteLn('Program ConsoleTest is running.');
    WriteLn('Press the ENTER key to stop');
    ReadLn;
  end
  else
  begin
    Application.Initialize;
    Application.MainFormOnTaskbar := True;
    Application.CreateForm(TfrmMain, frmMain);
    Application.Run;
  end;
Azad
  • 5,144
  • 4
  • 28
  • 56
  • Take a look at `AllocConsole` too, in MSDN. If you need a console associated with your GUI program, use that. You can call that anytime you need it (but only once, IIRC). – Rudy Velthuis Oct 02 '18 at 10:48
  • @azad The short answer is that you can fake it but it isn't very satisfactory. Do what Python and others do and create two executables. For Python, `python.exe` targets the console subsystem, `pythonw.exe` targets the GUI subsystem. – David Heffernan Oct 02 '18 at 11:13

1 Answers1

3

I am not sure if the IDE allows such code, but try:

uses
  Vcl.Forms,
  Winapi.Windows;

function GetConsoleWindow: HWnd; stdcall; 
  external 'kernel32.dll' name 'GetConsoleWindow';
function AttachConsole(ProcessId: DWORD): BOOL; stdcall; 
  external 'kernel32.dll' name 'AttachConsole';

const
  ATTACH_PARENT_PROCESS = DWORD(-1);

begin
  if ParamStr(1) = 'test' then
  begin
    if not AttachConsole(ATTACH_PARENT_PROCESS) then
      AllocConsole;
    Writeln('Yay! This is a console');
  end
  else
  begin
    Application.Initialize;
    Application.MainFormOnTaskbar := True;
    Application.CreateForm(TForm42, Form42);
    Application.Run;
  end;
end.

Do not use {$APPTYPE CONSOLE} here.

AttachConsole attaches to an existing (e.g. the parent) console.

AllocConsole attaches a console to the current process. You can even run it alongside the GUI and Writeln/Write to it from your GUI code.

Note that the process tries to attach to the parent console, if there is any. The program will write to that console, but it doesn't control it. So if someone (very likely the person that started the "GUI" program from the console) closes that parent console, the GUI program will close too (tried that several times).

If you want to prevent that, always AllocConsole a new one and use that exclusively. You may however end up with two consoles, the parent one (if there was any) and the new one. Make your choice.

Azad
  • 5,144
  • 4
  • 28
  • 56
Rudy Velthuis
  • 28,387
  • 5
  • 46
  • 94
  • 1
    in which module `AllocConsole` comes – Azad Oct 02 '18 at 11:07
  • 1
    See my edit: Winapi.Windows. – Rudy Velthuis Oct 02 '18 at 11:08
  • its a boolean type variable `function AllocConsole: BOOL; stdcall;` – Azad Oct 02 '18 at 11:10
  • @David: thanks. I don't know why, but I had in my mind that it returned an int. – Rudy Velthuis Oct 02 '18 at 11:10
  • Even if it did return an `int`, why you you test for that value being `> 0`? Pet hate of mine is testing `> 0` instead of `<> 0`. – David Heffernan Oct 02 '18 at 11:12
  • @Rudy Velthuis thank you very much its works as I expected.. – Azad Oct 02 '18 at 11:13
  • @David: laziness, I guess. May be your pet hate, but you are right, An int could have been negative. – Rudy Velthuis Oct 02 '18 at 11:16
  • 1
    @azad If what you expect is for a new console window to appear when you call your program from an existing console process, then yes, it works as you expect. As so many others before you have discovered, what you are attempting to do cannot be done perfectly. The right compromise is to have two executables, one targeting each subsystem. – David Heffernan Oct 02 '18 at 11:16
  • @DavidHeffernan is there any way to run the console application in same opened command prompt? – Azad Oct 02 '18 at 11:20
  • Not reliably. There are countless prior questions and articles on this subject. I suggest you research them. Don't limit your research to Delphi though because fundamentally this is a win32 question and the best resources will likely use C++ as their examples. – David Heffernan Oct 02 '18 at 11:22
  • @RudyVelthuis I downvoted this answer because it neglects so many of the subtleties of this topic. Again there are a great many prior articles on this that you should read. – David Heffernan Oct 02 '18 at 11:22
  • @azad: see my changes. Starts in console when started in console, but opens a new one when not. – Rudy Velthuis Oct 02 '18 at 12:02
  • @RudyVelthuis Keep reading, more work is needed – David Heffernan Oct 02 '18 at 12:07
  • So, Rob's answer here is a good place to start: https://stackoverflow.com/questions/493536/can-one-executable-be-both-a-console-and-gui-application – David Heffernan Oct 02 '18 at 12:15
  • This is always about the dicotomy between console mode and non-console mode programs. This is a non-console program. – Rudy Velthuis Oct 02 '18 at 14:51
  • @RudyVelthuis Hmm, I don't think you understand the issues here........ – David Heffernan Oct 02 '18 at 14:53
  • If you did, then you wouldn't suggest using `AttachConsole` like this, as described in the reference I provided. Or at the very least you'd mention that issue. – David Heffernan Oct 02 '18 at 15:11
  • @David. Perhaps I don't. My little demo seems to work fine. I know that that does not prove that it is correct, so perhaps I don't understand the issues. But none of the links I read seem to address anything telling me to do things differently. – Rudy Velthuis Oct 02 '18 at 15:39
  • @RudyVelthuis Fair enough. If you haven't personally experienced the problem, it's probably not real. – David Heffernan Oct 02 '18 at 15:48
  • Problems I have not personally experienced can be real. But it is well possible I don't know about them yet. – Rudy Velthuis Oct 02 '18 at 15:52
  • thank you very much you two made my day .. – Azad Oct 03 '18 at 04:23