This question is very similar (if not quite the same) as what I was trying to accomplish. I wanted to determine if my application was run from cmd.exe and send the output to the parent console, otherwise gui will appear in it. The answers here helped me solve my problem. Here is the code I came up with as an experiment:
ParentChecker.dpr
program ParentChecker; uses Vcl.Forms, SysUtils, PsAPI, Windows, TLHelp32, Main in 'Main.pas' {frmParentChecker}; {$R *.res} function AttachConsole(dwProcessID: Integer): Boolean; stdcall; external 'kernel32.dll'; function FreeConsole(): Boolean; stdcall; external 'kernel32.dll'; function GetParentProcessName(): String; const BufferSize = 4096; var HandleSnapShot: THandle; EntryParentProc: TProcessEntry32; CurrentProcessId: THandle; HandleParentProc: THandle; ParentProcessId: THandle; ParentProcessFound: Boolean; ParentProcPath: String; begin ParentProcessFound:=False; HandleSnapShot:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); if HandleSnapShot<>INVALID_HANDLE_VALUE then begin EntryParentProc.dwSize:=SizeOf(EntryParentProc); if Process32First(HandleSnapShot,EntryParentProc) then begin CurrentProcessId:=GetCurrentProcessId(); repeat if EntryParentProc.th32ProcessID=CurrentProcessId then begin ParentProcessId:=EntryParentProc.th32ParentProcessID; HandleParentProc:=OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,False,ParentProcessId); if HandleParentProc<>0 then begin ParentProcessFound:=True; SetLength(ParentProcPath,BufferSize); GetModuleFileNameEx(HandleParentProc,0,PChar(ParentProcPath),BufferSize); ParentProcPath:=PChar(ParentProcPath); CloseHandle(HandleParentProc); end; Break; end; until not Process32Next(HandleSnapShot,EntryParentProc); end; CloseHandle(HandleSnapShot); end; if ParentProcessFound then Result:=ParentProcPath else Result:=''; end; function IsPrime(n: Integer): Boolean; var i: Integer; begin Result:=False; if n<2 then Exit; Result:=True; if n=2 then Exit; i:=2; while i<(n div i + 1) do begin if (n mod i)=0 then begin Result:=False; Exit; end; Inc(i); end; end; var i: Integer; ParentName: String; begin ParentName:=GetParentProcessName().ToLower; Delete(ParentName,1,ParentName.LastIndexOf('\')+1); if ParentName='cmd.exe' then begin AttachConsole(-1); Writeln(''); for i:=1 to 100 do if IsPrime(i) then Writeln(IntToStr(i)+' is prime'); FreeConsole(); end else begin Application.Initialize; Application.MainFormOnTaskbar:=True; Application.CreateForm(TfrmParentChecker, frmParentChecker); frmParentChecker.Label1.Caption:='Executed from '+ParentName; Application.Run; end; end.
Main.pas (form with label):
unit Main; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, RzLabel; type TfrmParentChecker = class(TForm) Label1: TLabel; private { Private declarations } public { Public declarations } end; var frmParentChecker: TfrmParentChecker; implementation {$R *.dfm} end.
This allows me to launch my graphical application from the command line and output the output to the same console on which my application was running. Otherwise, it will launch the full part of the GUI application.
Example output from the console window:
I:\Delphi\Tests and Demos\ParentChecker\Win32\Debug>start /wait ParentChecker.exe 2 is prime 3 is prime 5 is prime 7 is prime 11 is prime 13 is prime 17 is prime 19 is prime 23 is prime 29 is prime 31 is prime 37 is prime 41 is prime 43 is prime 47 is prime 53 is prime 59 is prime 61 is prime 67 is prime 71 is prime 73 is prime 79 is prime 83 is prime 89 is prime 97 is prime I:\Delphi\Tests and Demos\ParentChecker\Win32\Debug>