How do I write to StdOut from a GUI app started from the command line?

后端 未结 8 2147
一向
一向 2021-02-09 05:52

I am writing a standard windows app in Delphi 7.

If I was writing a console app, I can call the following to output to the cmd line or output file.

write         


        
相关标签:
8条回答
  • 2021-02-09 06:19

    I did summarize this topic in a report with a running script too:

    http://www.softwareschule.ch/download/maxbox_starter70.pdf as a second backup:

    https://www.slideshare.net/maxkleiner1/nogui-maxbox-starter70

    the main routine has a nativewriteline to separate from writeline:

     for it:=1 to 50 do if IsPrime(it) then NativeWriteln(IntToStr(it)+' is prime');
    
    0 讨论(0)
  • 2021-02-09 06:23

    Call AllocConsole to avoid the error 105.

    0 讨论(0)
  • 2021-02-09 06:25

    I'm not quite sure what you are trying to achieve.
    As I understood the question one way could be

    program Project1;
    {$APPTYPE CONSOLE}
    
    uses
      Forms, Classes, Windows,
      Unit1 in 'Unit1.pas' { Form1 } ;
    {$R *.res}
    
    var
      Finished: Boolean;
      Input: String;
    
    function IsConsoleMode(): Boolean;
    var
      SI: TStartupInfo;
    begin
      SI.cb := SizeOf(TStartupInfo);
      GetStartupInfo(SI);
      Result := ((SI.dwFlags and STARTF_USESHOWWINDOW) = 0);
    end;
    
    procedure HandleInput;
    begin
      Finished := Input = 'quit';
      if not Finished then
      begin
        Writeln('Echo: ' + Input);
      end
      else
        Writeln('Bye');
    end;
    
    begin
      if IsConsoleMode then
      begin
        Finished := false;
        Writeln('Welcome to console mode');
        while not Finished do
        begin
          readln(Input);
          HandleInput;
        end;
      end
      else
      begin
        Writeln('Entering GUI Mode');
        FreeConsole;
        Application.Initialize;
        Application.MainFormOnTaskbar := True;
        Application.CreateForm(TForm1, Form1);
        Application.Run;
      end;
    
    end.
    
    0 讨论(0)
  • 2021-02-09 06:25

    There's no reliable way for a GUI subsystem application to attach to the console of its parent process. If you try to do so you end up with two active processes sharing the same console. This leads to no end of trouble.

    The alternative, whilst retaining just a single executable, as suggested by bummi, is to have a console app that frees its console if it is asked to run in GUI mode. This is a better approach, but leads to a console window flashing up, and then closing, when you want to run in GUI mode.

    The best discussion of the subject that I have come across on Stack Overflow is Rob Kennedy's superb answer: Can one executable be both a console and GUI application?

    I believe, from what you say in comments, that the best option for you is to create two separate executables. One for the GUI subsystem, and one for the console subsystem. This is the approach taken by:

    • Java: java.exe, javaw.exe.
    • Python: python.exe, pythonw.exe.
    • Visual Studio: devenv.com, devenv.exe.

    Yes you have to ship multiple executables. But doing so gives the user the best experience.

    0 讨论(0)
  • 2021-02-09 06:26

    FWIW, I played around with this problem and happened upon AttachConsole which seems to do the trick. The only problem I ran into with my code is that the program won't give the console up without an extra ENTER key or two. It's not real polished since I was trying to fix that problem and (kind of) gave up. Perhaps someone here will see it?

    program writecon; uses windows, dialogs;
    
      function AttachConsole(dwProcessID: DWord): BOOL; stdcall; external 'kernel32.dll';
    
      function load_attach_console: boolean;
        begin
          Result := AttachConsole(-1);
        end;
    
      begin
        // the function requires XP or greater, you might want to check for that here.
        if load_attach_console = true then
          begin
            writeln;
            writeln('This is running in the console.');
            write('Press ENTER to continue.');
            readln;
            // from the linked page, you have to detach yourself from the console
            // when you're done, this is probably where the problem is.
            Flush(Output);
            Flush(Input);
            FreeConsole;
          end
        else
          MessageDlg('This is not running in the console.', mtInformation, [mbOk], 0);
      end.
    
    0 讨论(0)
  • 2021-02-09 06:40

    AttachConsole does seem to work, as noted above it waits for ENTER.

    However, the program is still a win prog and not a console program as far as dos sees it, and so cmd proceeds to the next command after launching it.

    test.exe & dir
    

    shows the dir listing first, then the output from test.exe

    start /w test.exe & dir 
    

    does work, and does not pause for ENTER key

    BTW, the suggestion above: PostMessage(GetCurrentProcess,$0101,$0D,0); does the ENTER but is giving a bong noise.

    0 讨论(0)
提交回复
热议问题