Visit our Sponsor   Visit our Sponsor
delphi3000.com - the free delphi knowledge platform
delphi3000.com - the free delphi knowledge platform
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







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 (7)


Update: 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 with in 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 delphi delphi3000 article console output capture capturing DOS MSDOS MS-DOS command-line command get getting prompt output-window 16-bit createprocess redirect redirecting
Times Scored:
11
Visits:
10870
Uploader: John W. Long
Company:
Reference: N/A
 
Question/Problem/Abstract:
In my article http://www.delphi3000.com/articles/article_2112.asp posted a function for retrieving all of the output of a console application. Unfortunately, though it worked fine on 32-bit apps it did not work well with 16-bit apps. This was not a problem with the code, but rather a bug in Windows (http://support.microsoft.com/support/kb/articles/Q150/9/56.ASP). But how can this be done?
Answer:



{
Here is new function I have been working on which seems to do the trick.  It bypasses the problem with 16-bit apps by directing windows to send the output to a text file, and then reads it back in, deletes the file, and sends the result back to you.  Be careful when calling this with command.com.  Because it waits on the process infinitely it will hang on this because command.com waits for user input...

Special thanks to Theo Bebekis for his help on this.

If you have questions or comments please email me  at johnwlong@characterlink.net, I have not had a chance to thoroughly test this version so any feed back would be helpful.
}

function GetConsoleOutput(const CommandLine:string): string;
var
  SA: TSecurityAttributes;
  SI: TStartupInfo;
  PI: TProcessInformation;
  StdOutFile, AppProcess, AppThread : THandle;
  RootDir, WorkDir, StdOutFileName:string;
const
  FUNC_NAME = 'GetConsoleOuput';
begin
  try
    StdOutFile:=0;
    AppProcess:=0;
    AppThread:=0;
    Result:='';

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

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

   // Initialize output file security attributes
    FillChar(SA,SizeOf(SA),#0);
    SA.nLength:=SizeOf(SA);
    SA.lpSecurityDescriptor:=nil;
    SA.bInheritHandle:=True;

    // Create Output File
    StdOutFileName:=RootDir+'output.tmp';
    StdOutFile:=CreateFile(PChar(StdOutFileName),
                   GENERIC_READ or GENERIC_WRITE,
                   FILE_SHARE_READ or FILE_SHARE_WRITE,
                   @SA,
                   CREATE_ALWAYS, // Always create it
                   FILE_ATTRIBUTE_TEMPORARY or // Will cache in memory
                                               // if possible
                   FILE_FLAG_WRITE_THROUGH,
                   0);

    // Check Output Handle
    if StdOutFile = INVALID_HANDLE_VALUE then
      raise Exception.CreateFmt('Function %s() failed!' + #10#13 +
        'Command line = %s',[FUNC_NAME,CommandLine]);

    // Initialize Startup Info
    FillChar(SI,SizeOf(SI),#0);
    with SI do begin
      cb:=SizeOf(SI);
      dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
      wShowWindow:=SW_HIDE;
      hStdInput:=GetStdHandle(STD_INPUT_HANDLE);
      hStdError:=StdOutFile;
      hStdOutput:=StdOutFile;
    end;

    // Create the process
    if CreateProcess(nil, PChar(CommandLine), nil, nil,
                     True, 0, nil,
                     PChar(WorkDir), SI, PI) then begin
      WaitForSingleObject(PI.hProcess,INFINITE);
      AppProcess:=PI.hProcess;
      AppThread:=PI.hThread;
      end
    else
      raise Exception.CreateFmt('CreateProcess() in function %s() failed!'
                   + #10#13 + 'Command line = %s',[FUNC_NAME,CommandLine]);

    CloseHandle(StdOutFile);
    StdOutFile:=0;

    with TStringList.Create do
    try
      LoadFromFile(StdOutFileName);
      Result:=Text;
    finally
      Free;
    end;

  finally
    // Close handles
    if StdOutFile <> 0 then CloseHandle(StdOutFile);
    if AppProcess <> 0 then CloseHandle(AppProcess);
    if AppThread <> 0 then CloseHandle(AppThread);

    // Delete Output file
    if FileExists(StdOutFileName) then DeleteFile(StdOutFileName);
  end;

end;





Please rate this article!
Skill level:
BeginnerExpert

Useful:
No!Very!

Overall rating:
PoorExcellent



Comments to this article
Write a new comment
:/
    Michal Poznanski (May 4 2005 8:13PM)

not working under XP
Respond

My ass hurts...
    Aram Dook (Jul 23 2004 10:29PM)

thankx for the reamin'
Respond

Nice, but ...
    Ruud Bijvank (May 31 2001 8:56AM)

Nice tip, but...
You'll get the output when the process has finished. It would be really great if you could capture the output when the process still runs (so, live!)
Respond

RE: Nice, but ...
Jim Burns (Apr 6 2002 9:03AM)

This comes with it's own set of challenges.  It's more susceptable to the Win98 bug.  

But I've been working on a function that does just this.  I don't have time to figure out if or how I can post an article here, if you'd like it shoot me a note, and I'll send it.  
Respond

RE: RE: Nice, but ...
Jim Burns (Apr 8 2002 8:18PM)

My original comments were in response to wanting to spawn a console process and instead of waiting for the process to complete, to retrieve the data as it is output from the spawned process.  

Since the Win95/98/Me redirect bug for 16-bit process' specifically involves inherited redirected I/O, actively receiving this data while the console runs is more dependent upon a good solution to this bug.  For example, even with the bug, if you wait for termination of a 16-bit console app, you'll probably still retrieve all the data it output.  At least I did, and I never encountered this bug until I started wanting to read my end of the pipe during the running of the console app.  In fact, I was really scratching my head at first because my ReadFile would block on the last call if my logic was the sort of logic we expect to use, (i.e. checking the result, checking bytes returned)  but I /could/ receive all the data IF I could somehow use different logic.  Anyway, the long and the short of it is the issue is a bit stickier given this bug.

The MS KB articles that made it all clear for me can be found at,

  http://support.microsoft.com/default.aspx?scid=kb;EN-US;q150956
  http://support.microsoft.com/default.aspx?scid=kb;en-us;Q190351

Also, here's a link to my sample and testing app.  It's the function I use, the code for the 32-bit console stub, SpawnConsole32, and executables for both the stub and  the demo app I used for testing.  Be advised, the demo app relies on the stub, so put them in the same directory.
   http://www.technologydynamics.com/software/downloads/ExecuteRedirectedConsole.zip

I'm a professional, my system is virus free, but please at your end remember to scan the files first so we can both be assured the files are safe.

The testing app will allow you to type in a command and parameters and see the output of the spawned console in the UI.

Jim Burns
Technology Dynamics
Pearland, TX
Respond

Dos App Redirecting
dfmnbdf lkjhdfglkjh (Sep 7 2003 4:25AM)

First off this is not my real email. its coolest@tampabay.rr.com

Second off, :D Do you by chance know how to redirect the output as it comes. I need to be able to import a dos program into a memo pad but its a menu program. I just need to get the output and be able to send it keyboard commands. please please please please help. I have looked for like 2 months to solve this problem. Thanks agin!
Respond

Great Tip.
    Bill Pollifrone (May 25 2001 11:31AM)

Nice tip. The file would be better if it was a mailslot, but I don't recall the 16-bit supporting a mailslot. ;-)
Respond














 
Sign up to consume product discounts for Bronze memberships !

read more


  Visit our Sponsor

 

  Community Ad of
I. Siticov
 
   














 







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