Running a DOS program from within a DELPHI program

LenB used Ask the Experts™
I need to know how to run a DOS program (32-bit) from within a DELPHI 3.0 program.

Usually, the DOS program is run in a DOS window and accepts a command line parameter.  I need my program to automatically create such a window and to call the program together with its command line parameter.

I know about the CreateProcess function but I can't get it to work.  I would appreciate being able to look at a working example if you have one and don't mind parting with it.

Thanks in advance.


Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
WinExec('c:\something.exe', SW_SHOW);
This command is 16bit based but it will work with delphi3.

I only know something about it for Delphi 2.0 & Delphi 1.0 but I think Delphi 3.0 won't be that different from Delphi 2.0, I can give you some code, but there are a lot of components around with the full source and an example, so I think you can look at them first. If you still want some code, I can give it to you, but look at the next lines and proposals first :

This question is already asked for a 16bit environment. But there is also the answer for 32bit environments. It's a little bit difficult for 16bit. Because of that they proposed a component called XSpawn from HyperAct. It's freeware now and because of that they don't give support anymore. I took it from their site and i'm using it. The great thing of this component is that you can use it on every OS (Windows 3.1/3.11/95/NT, OS/2)

But if you just want a component (with source) for 32bit and windows 95 and NT you can also use the following component :

I've also used this component, it's great with a good documentation. It's written by Kevin Savko

Hope you're something with this, if not just give a comment and I'll see what I can do.


Oh yes, something else. The component of Kevin Savko doesn't support the error codes of your dos program. I mean, if the DOS program gives an error when it exits, you can't get it. But that isn't a big deal, because I've changed the code a little bit, and now you can get the error code from the program. So if you want the changed code, just ask!
                              c.u. ZifNab

CompTIA Security+

Learn the essential functions of CompTIA Security+, which establishes the core knowledge required of any cybersecurity role and leads professionals into intermediate-level cybersecurity jobs.

WinExec is for compatibility with 16bit programs but it call CreateProcess so can run all program's. Why you can't use this.
Try WinExec( 'your.exe param1 param2', SW_SHOW ) this work fine!
Hi all,

Sorry, but I thought WinExec, is only for windows-based applications, not DOS? Am I wrong? But try this, it' s the heart of Kevin Savko's code, which I earlier mentioned.

function TExecFile.Execute: Boolean;
var zCommandLine: array[0..512] of Char;
zFAssFName: array[0..255] of Char;
zFAssFDir: array[0..255] of Char;
zFAssFDoc: array[0..255] of Char;
FSuccess: Boolean;

StartupInfo.cb := Sizeof(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;

If FWindowStyle = wsNorm then StartupInfo.wShowWindow := SW_SHOWNORMAL;
If FWindowStyle = wsMinimize then StartupInfo.wShowWindow := SW_SHOWMINIMIZED;
If FWindowStyle = wsMaximize then StartupInfo.wShowWindow := SW_SHOWMAXIMIZED;
If FWindowStyle = wsHide then StartupInfo.wShowWindow := SW_HIDE;
If FWindowStyle = wsMinNoActivate then StartupInfo.wShowWindow := SW_SHOWMINNOACTIVE;
If FWindowStyle = wsShowNoActivate then StartupInfo.wShowWindow := SW_SHOWNA;

If FPriorityClass = pcHigh then FPriorityValue := HIGH_PRIORITY_CLASS;
If FPriorityClass = pcIdle then FPriorityValue := IDLE_PRIORITY_CLASS;
If FPriorityClass = pcNormal then FPriorityValue := NORMAL_PRIORITY_CLASS;
If FPriorityClass = pcRealTime then FPriorityValue := REALTIME_PRIORITY_CLASS;

StrPCopy(zCommandLine,FCommandLine+' '+FFParams);

FSuccess := CreateProcess(nil,
      zCommandLine,           { 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 }
      nil,                    { pointer to new environment block }
      nil,                    { pointer to current directory name }
      StartupInfo,            { pointer to STARTUPINFO }

If not FSuccess then begin
 If FAss then begin StrPCopy(zFAssFDoc,FCommandLine);
  If findExecutable(zFAssFDoc,zFAssFDir,zFAssFName)<32 then begin
   FError := GetLastError(); If Assigned(FOnFail) then FOnFail(Self);
   Result := False; exit;
  end else begin FAssFName := zFAssFName;
   StrPCopy(zCommandLine,FAssFName+' '+FCommandLine+' '+FFParams);
   FSuccess := CreateProcess(nil,
      zCommandLine,           { 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 }
      nil,                    { pointer to new environment block }
      nil,                    { pointer to current directory name }
      StartupInfo,            { pointer to STARTUPINFO }

If FSuccess then begin
  If FWait then begin FIsWaiting := True; FStopWaiting := False;
   If FWaitStyle = wRegular then begin
     While PeekMessage(FMsg,0,0,0,PM_REMOVE) do begin
     If FMsg.Message = WM_QUIT then halt(FMsg.wParam);
     TranslateMessage(FMsg); DispatchMessage(FMsg); end;
     If WaitforSingleObject(ProcessInfo.hProcess,0)<>WAIT_TIMEOUT then begin
     FStopWaiting := True; Application.ProcessMessages; end;
     Until FStopWaiting; end
   else begin
   WaitForSingleObject(ProcessInfo.hProcess,INFINITE); end;
  FIsWaiting := False; Result:= True; end;
end else begin
 FError := GetLastError(); If Assigned(FOnFail) then FOnFail(Self);
 Result := False; end;

ZifNab - Yes you are wrong !  WinExec is for dos program's too and work fine win WinNT too it is very easy for runnig program's. You must go to CreateProcess only if You need acces  to this new process (for example exit code or when you need terminate this process).

Mirek & Len,


Thanks for correcting my mistake!
But as I can read from your comment, you need to use CreateProcess if you want the exit codes of a DOS program. Am I correct, because if not I'll get a heart attack? Then I've always  worked too much. And all that work can be combined in one code-line. Please don't say, that I've worked too much!!!


If you don't need the exit codes, if you just want to start a program, then please reject my answer and use mireks answer. That's far more easier!!! Otherwise, look at the examples I gave  you and see if they work out for you.


Hi ZifNab.
Sorry for my comment. You'r code is ok, but LenB don't say so must wait for terminate process and When reject answer from ronit he(/she) dont say why.
Of course you made mistake with words about WinExec.

p.s. Nice to see New Expert. Here are many qestions awaiting answers.


Thanks to all three Experts who commented on my question.

I apologize for not being specific enough about what I wanted.

The reason I was after a solution involving CreateProcess is as follows:

The DOS program is not interactive but processes instructions from a text file given as a command line parameter.  It can take a long time to run (2 to 60 minutes - depending on the instruction file).  Whilst running, it will be writing some stuff (text and numeric parameters) to its DOS window.  I would like the DOS window to be invisible, and to be able to capture this text and use dialog boxes to display the parameters as the DOS process runs.  

The DOS program does a lot of least-squares refinements on a lot of data, and if the Esc key is pressed, it will neatly jump to the next cycle.  If the Ctrl-C key is pressed, it will treat the current refinement as the last cycle and terminate neatly.
So, I would like to be able to feed either an Esc character or a Ctrl_C to the DOS window if the user wants to cut the run short (by pressing an appropriate button in a dialog box) - but I don't necessarily want the ability to kill the process outright.

I didn't think I would be able to do all this with a simple call to WinExec - but maybe I can?  I'm pretty new to Windows programming.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial