Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
487 Users Online NOW
Have a look at your member-status

connecting people's knowledge


  - Recent ArticlesRSS feed for Recent Articles on delphi3000.com
  - List of All Articles
  - Top Viewed Articles
  - Articles (+Attachem.)
  - Articles Of Interest
  - Categories
  - Top Uploader
  - Search
  - Index

  - My Home
  - Submit an Article
  - My Articles
  - My Personal Data
  - My Bookmarks
  - Activities
  - Login/Logout

  - Sign Up
  - Why Sign Up
  - Newsletter

  - Press
  - Advertise

  - Contact
  - Feedback





Community
Borland
ClubeDelphi
Dr. Bob
UK-BUG
Delphi Meetings
Planeta Delphi



Loremo - the 1.5 liter car coming in 2009




Startblatt.de






Share this article with friendsShare this article with friends
Rate this articleRate this article - to keep the quality of delphi3000.com !
Comment this article or read through previous comments (10)


Capturing all of the Output from a Console applicationGo to John W. Long's websiteFormat this article printer-friendly!Bookmark function is only available for registered users!
Great for an output window within your application
Product:
Delphi all versions
Category:
Win API
Skill Level:
Scoring:
Last Update:
05/23/2001
Search Keys:
delphi delphi3000 article borland vcl code-snippet console output capture capturing DOS MSDOS MS-DOS command-line command get getting prompt output-window
Times Scored:
14
Visits:
10468
Uploader: John W. Long
Company:
Reference: N/A
 
Question/Problem/Abstract:
Use the function GetDosOutput in your application to capture all the output from a DOS application (this version only supports 32-bit console applications for how to do this with 16 bit see the update to this article http://www.delphi3000.com/articles/article_2298.asp).

Code recieved from Mike Lischke (Team JEDI) in response to a question I asked on the borland winapi newsgroup.  It came from his app "Compiler Generator" (www.lischke-online.de/DCG.html) and then was converted to the GetDosOutput function by me.  You can contact me at johnwlong@characterlink.net.
Answer:



unit consoleoutput;

interface

uses
  Controls, Windows, SysUtils, Forms;

function GetDosOutput(const CommandLine:string): string;

implementation

function GetDosOutput(const CommandLine:string): string;
var
  SA: TSecurityAttributes;
  SI: TStartupInfo;
  PI: TProcessInformation;
  StdOutPipeRead, StdOutPipeWrite: THandle;
  WasOK: Boolean;
  Buffer: array[0..255] of Char;
  BytesRead: Cardinal;
  WorkDir, Line: String;
begin
  Application.ProcessMessages;
  with SA do
  begin
    nLength := SizeOf(SA);
    bInheritHandle := True;
    lpSecurityDescriptor := nil;
  end;
  // create pipe for standard output redirection
  CreatePipe(StdOutPipeRead,  // read handle
             StdOutPipeWrite, // write handle
             @SA,             // security attributes
             0                // number of bytes reserved for pipe - 0
default
             );
  try
    // Make child process use StdOutPipeWrite as standard out,
    // and make sure it does not show on screen.
    with SI do
    begin
      FillChar(SI, SizeOf(SI), 0);
      cb := SizeOf(SI);
      dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
      wShowWindow := SW_HIDE;
      hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect std
input
      hStdOutput := StdOutPipeWrite;
      hStdError := StdOutPipeWrite;
    end;

    // launch the command line compiler
    WorkDir := ExtractFilePath(CommandLine);
    WasOK := CreateProcess(nil, PChar(CommandLine), nil, nil, True, 0, nil,
PChar(WorkDir), SI, PI);

    // Now that the handle has been inherited, close write to be safe.
    // We don't want to read or write to it accidentally.
    CloseHandle(StdOutPipeWrite);
    // if process could be created then handle its output
    if not WasOK then
      raise Exception.Create('Could not execute command line!')
    else
      try
        // get all output until dos app finishes
        Line := '';
        repeat
          // read block of characters (might contain carriage returns and
line feeds)
          WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);

          // has anything been read?
          if BytesRead > 0 then
          begin
            // finish buffer to PChar
            Buffer[BytesRead] := #0;
            // combine the buffer with the rest of the last run
            Line := Line + Buffer;
          end;
        until not WasOK or (BytesRead = 0);
        // wait for console app to finish (should be already at this point)
        WaitForSingleObject(PI.hProcess, INFINITE);
      finally
        // Close all remaining handles
        CloseHandle(PI.hThread);
        CloseHandle(PI.hProcess);
      end;
  finally
      result:=Line;
      CloseHandle(StdOutPipeRead);
  end;
end;


end.








Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
not working in XP
    Michal Poznanski (May 5 2005 1:50AM)

not working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XPnot working in XP
Respond

Thanks!
    Jamie Kitson (Feb 10 2005 3:03PM)

Thanks for that, just what I needed.

btw, if you want to use parameters do something like this:

    Params := ExeFile + ' ' + Params;
    WasOK := CreateProcess(PChar(ExeFile), PChar(Params), nil, nil, True, 0, nil, PChar(WorkDir), SI, PI);

Respond

Memory Usage
    al kinnnon (Oct 10 2002 5:42PM)

This is a great piece of code, however, I have a problem when using it.
I have a timer on my main application which calls this, passing in a valid command.
After each call, the memory usage for my application increases.
When I ran a test, calling it every 5 seconds, the machine crashed within half an hour.
Can you help?

Thanks,
Allan.
Respond

Could not execute command line!
    Shannon Wynter (Sep 3 2001 3:47AM)

I've set up a program that uses this unit to execute a perl script with active perl (www.activeperl.com)

Every time I attempt it I get "Could not execute command line!".
I've debugged and pulled the exact command line from the program and used the start/run in explorer and it works perfectly.

Ideas as to why this is so?

commandline="E:\Perl\bin\perl.exe c:\windows\temp\re21313.pl"

Thanks

Shannon
Respond

RE: Could not execute command line!
John W. Long (Sep 11 2001 6:13PM)

Off the top of my head this is because WorkDir is not being initialized properly.  You might try putting quotes around the parameter, or replacing the "WorkDir:= ..." code with:

    // Initialize dirs
    RootDir:=ExtractFilePath(ParamStr(0));
    WorkDir:=ExtractFilePath(CommandLine);

    // Check WorkDir
    if not (FileSearch(ExtractFileName(CommandLine),WorkDir)<>'') then WorkDir:=RootDir;

Also try the version that works with 16-bit programs if that doesn't help drop me an email...
Respond

RE: Could not execute command line!
ajay sharma (Feb 20 2002 1:38PM)

Hi,
I too am using the activeperl distribution and trying to execute the perl compiler through the command line.
Commandline :='c:\perl\bin\Perl.exe c:\myexamples\noname1.pl'
When I hard code the commandline string, the program works.
But when I put a variable in the command line, it gives an error.

x:='c:\myexamples\noname1.pl';
Commandline:='c:\perl\bin\perl.exe' + ' ' + x;

I have tried to put quotes with the help of quotedstr, but either an error occurs, or the perl compiler cannot find the file.

This perl compiler is for win32 systems only.

Regards
Ajay Sharma
Respond

RE: RE: Could not execute command line!
someone (Jul 25 2004 12:55AM)

I had somehow the same problem.

I wanted to display a directory (result of dir c:\).

The solution was to split the input of the function getdosdoutput into two variables, one containing  cmd.exe (with full path!) and the other one the arguments.

Change the function createProcess( nil, pchar(commandline), ....   into createProcess( pchar(-path\program-),  pchar(arguments), ..... and stuf works.
Respond

Warning for 16-bit apps
    Joe White (Apr 16 2001 1:08PM)

According to MSDN Online, this can cause your program to hang if the console app you're calling is 16-bit. A workaround is at http://support.microsoft.com/support/kb/articles/Q150/9/56.ASP.
Respond

RE: Warning for 16-bit apps
John W. Long (Apr 17 2001 8:20PM)

I'm working on a function that does this with 16-bit apps. It is almost ready for posting. If you would like a version of it please email me: johnwlong@characterlink.net
Respond

RE: RE: Warning for 16-bit apps
John W. Long (May 23 2001 10:36AM)

This has been fixed in a my new article: http://www.delphi3000.com/articles/article_2298.asp
Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
M. Kleiner
 
   














 







     
  Copyright © 2000 - 2007 delphi3000.com - All rights reserved. Terms of use. || Privacy
delphi3000.com is a service by bluestep.com IT-Services GmbH (Vienna)