Solved

Running DOS programs from a Delphi app

Posted on 1998-12-28
15
224 Views
Last Modified: 2010-04-04
Can I run a DOS program from inside my Delphi app in such a way that my program waits for the DOS program to end (something like a "modal" DOS program)?
0
Comment
Question by:sandman_br
  • 6
  • 4
  • 2
  • +2
15 Comments
 
LVL 17

Accepted Solution

by:
inthe earned 30 total points
Comment Utility
hi
stick one button on a form (name is button3)
then paste this code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button3: TButton;
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

function WinExecAndWait32(FileName:String; Visibility :integer):integer;
  var
    zAppName:array[0..512] of char;
     zCurDir:array[0..255] of char;
     WorkDir:String;
     StartupInfo:TStartupInfo;
     ProcessInfo:TProcessInformation;
 begin
     StrPCopy(zAppName,FileName);
     GetDir(0,WorkDir);
     StrPCopy(zCurDir,WorkDir);
     FillChar(StartupInfo,Sizeof(StartupInfo),#0);
     StartupInfo.cb := Sizeof(StartupInfo);
     StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
     StartupInfo.wShowWindow := Visibility;
 if not CreateProcess(nil,zAppName,  { pointer to command line string }
       nil,            {pointer to process security attributes }
       nil,            { pointer to thread security attributes }
       false,                     { handle inheritance flag }
       CREATE_NEW_CONSOLE or      { creation flags }
       NORMAL_PRIORITY_CLASS,
       nil,                     { pointer to new environment block }
       nil,                      { pointer to current directory name }
       StartupInfo,                   { pointer to STARTUPINFO }
       ProcessInfo) then Result := -1 { pointer to PROCESS_INF }
     else
        begin
        WaitforSingleObject(ProcessInfo.hProcess,INFINITE);
        GetExitCodeProcess(ProcessInfo.hProcess,Result);
        CloseHandle( ProcessInfo.hProcess );
        CloseHandle( ProcessInfo.hThread );
        end;
   end;
procedure TForm1.Button3Click(Sender: TObject);
begin
WinExecAndWait32('c:\edit.com',1);
Close;
end;
end.
hope it shows you what you need
Regards Barry
0
 
LVL 1

Expert Comment

by:martin_g
Comment Utility
I've used a simple approach with success.  Use FileExecute() found in the FMXUtils.pas that ships with Delphi.
Here's an example:
ExecuteFile ('gencri.exe',,SW_SHOWMINIMIZED);

You can put command line parameters for your DOS app between the two commas.

REFERENCE: From Delphi 3 Help under FileExecute -
"Many times an application needs to execute another application, either to perform a specific task or just to have that application run concurrently. The Windows API provides a function, ShellExecute, that executes an application, but it requires a number of parameters superfluous to Delphi applications. The FMXUtils unit provides a more useful alternative, called ExecuteFile.
ExecuteFile operates in two different ways. If passed the name of an executable file, ExecuteFile runs that application. If passed the name of a document with an associated application, ExecuteFile runs the application, automatically opening that document at startup."

Hope this helps.

0
 
LVL 17

Expert Comment

by:inthe
Comment Utility
martin_q
 the whole point was to execute and wait. try running your way and putting close statement after execute file,sure it opens the file but it dont wait.(or at least i cant get it to)
executefile is calling shellexecute as you say but shellexecute is calling createprocess so why not go straight to createprocess
and tweak a bit to get dos prog to wait like in code above.
please correct me if im wrong  :-)
Regards Barry
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
Hi Barry,

your sources look nice, but not enough (I'm a perfectionist). The problem with your sources is that your application doesn't process messages while waiting on the dos program. That means that the main form isn't repainted anymore and all that stuff.
So here comes my solution (thread based) that solves this problem, too.

sandman_br, my sources copies the "autoexec.bat" file, and waits until this is ready. Then you'll find the output text in 'c:\output.txt'. Furthermore the dos window is hidden. If you don't like that, just remove the line:
  si.dwFlags:=STARTF_USESHOWWINDOW; si.wShowWindow:=SW_HIDE;

Regards, Madshi.

unit runThread_;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, tools, ddraw;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen}
  public
    { Public-Deklarationen}
  end;

var Form1 : TForm1 = nil;

implementation

{$R *.DFM}

const unitName = 'runThread_.';

type TRunThread = class(TThread)
  private
    processHandle : cardinal;
    processReady  : boolean;
    waitingThread : cardinal;
    procedure Execute; override;
  end;

procedure TRunThread.Execute;
begin
  WaitForSingleObject(processHandle,INFINITE);   // This call does not return, unless copy is stopped
  processReady:=true;                            // Set "processReady" flag for main thread
  PostThreadMessage(waitingThread,WM_NULL,0,0);  // Wake up main thread
                                                 // If you call Application.HandleMessage (see below) in the
                                                 // main thread, the main thread is sleeping the most time in
                                                 // winAPI "waitMessage". So we send a "dummy" message in order
                                                 // to let the main thread return from Application.HandleMessage
end;

procedure TForm1.Button1Click(Sender: TObject);
var si : TStartupInfo;
    pi : TProcessInformation;
begin
  caption:='start copy...';
  ZeroMemory(@si,sizeOf(si)); si.cb:=sizeOf(si);
  si.dwFlags:=STARTF_USESHOWWINDOW; si.wShowWindow:=SW_HIDE;
  if CreateProcess(nil,'c:\command.com /c copy c:\autoexec.bat c:\test.bat >c:\output.txt',nil,nil,false,0,nil,nil,si,pi) then begin
    caption:='copy started...';
    with TRunThread.Create(true) do         // create the thread object, but do not start it now...
      try
        processHandle:=pi.hProcess;         // tell the thread what process it has to watch
        processReady:=false;                // flag for the loop (see below)
        waitingThread:=GetCurrentThreadID;  // the current threadID for the wakeup message (see above)
        caption:='wait for copy...';
        Resume;                             // now all information is prepared; so let's start the thread
        repeat
          Application.HandleMessage;        // message loop
        until Application.Terminated or processReady;  // continue with normal program when either the
                                                       // started process has stopped or our program is closed
        caption:='copy stopped...';
      finally Free end;
    CloseHandle(pi.hThread); CloseHandle(pi.hProcess); // Never forget to close handles...
    caption:='ready...';
  end else caption:='could not start copy...';
end;

end.
0
 

Author Comment

by:sandman_br
Comment Utility
Hi guys,
Barry's code worked great. My app's main window won't get repainted until the DOS program ends, as Madshi pointed, but I can live with that :) Madshi, I tried your code too, but the app was still accessible to the user while the DOS prog was running... but thanks for your efforts.
Thanks everyone!

Best regards,
Roger
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
Hmmm. If you want your main window to be disabled, you just need to call "form1.enabled:=false" before starting the dos program and "form1.enabled:=true" after coming back...
0
 

Author Comment

by:sandman_br
Comment Utility
Hi Madshi,
Thanks for the last comment, that finishing touch makes your solution perfect. I'm just a beginner in Delphi and had not realized I could use that... thanks a lot!
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 20

Expert Comment

by:Madshi
Comment Utility
No problem...   :-)
0
 
LVL 17

Expert Comment

by:inthe
Comment Utility
yes thanks for your input madshi the more ways to know how to do something the better then we can use all the best bits and have perfection eh :-)
Regards Barry
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
:-)  perfection... Yeah!!   :-)
0
 
LVL 2

Expert Comment

by:SupWang
Comment Utility
hi, inthe
I used your code in Delphi 3, it work Ok. But In Delphi 4, "GetExitCodeProcess(ProcessInfo.hProcess,Result)" could not be compiled. The Error Messsage: Types of actual and formal var parameters must be identical My Delphi version is Version 4.0(Build 5.104) Update Pack 2. why? :-(

Regards,
SupWang
0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
SupWang,

change the result type of the function "WinExecAndWait32" to cardinal.
In D3, integer and cardinal were almost identical. In D4, they are incompatible.

Regards, Madshi.
0
 
LVL 17

Expert Comment

by:inthe
Comment Utility
hi all
thanks madshi ,just got in and seen comment
we have to be more careful now with all different versions of delphi being slightly different eh.
Regards Barry
0
 
LVL 2

Expert Comment

by:SupWang
Comment Utility
Hi, Madshi
Thanks :-)
Regards,SupWang

0
 
LVL 20

Expert Comment

by:Madshi
Comment Utility
No prob...  :-)

I really like it that D4 has no a "real" cardinal type, but unfortunately that makes some problems, too...

Regards, Madshi.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
How to convert wav to mp3 in delphi 9 137
Newbie Thread Programming 1 116
Delphi Form ownership 4 50
Reconfigure Delphi Install? 2 34
A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now