Board index » delphi » Delphi: Making a shell-program

Delphi: Making a shell-program

Hello!

I want to make a program that executes an other program and pauses
until this program ends.

By using the function ExecuteFile(...) I can start an other program,
but the main-program doesn't pause.

Is there a kind of "modal"-function for a form? Could that be used?

If there a way to find out what other programs are running at a given
time, I may use that instead. Is there any?

Greatfull for any answer; either to this group or by email!

Sven H. Enger
sve...@oslonett.no

 

Re:Delphi: Making a shell-program


In a previous article, sve...@oslonett.no (Sven H. Enger) says:

Quote
>Hello!

>I want to make a program that executes an other program and pauses
>until this program ends.

>By using the function ExecuteFile(...) I can start an other program,
>but the main-program doesn't pause.

>Is there a kind of "modal"-function for a form? Could that be used?

>If there a way to find out what other programs are running at a given
>time, I may use that instead. Is there any?

>Greatfull for any answer; either to this group or by email!

        In my latest program, I had to do exactly the same thing.  It
takes some Windows API calls, but it can be done.  Here is how my
program does it:

1) I disable the form (in this case, called OpeningScreen), by setting
the Enabled property to false and, to make it _look_ disabled, disable
all of the components on the form too.

2) Shell out to the program.

3a) If you didn't write the other program, but know it has a unique class
name, execute a loop like so:

while FindWindow(ClassName, nil) <> 0 do (DoEvents);

        ClassName is either a variable of PChar (array[0..n] of char) or
a string constant.  If you don't know the class name, or has a common one
like ThunderForm (VB's only class name), you can use nil in the classname
and pass the caption instead for the second parameter, but that only
works when the caption of the called program never changes.

        The problem with that is, as I'm sort of new to Delphi, I don't
know its equivelent to DoEvents, so I can't yield control to the system
and not hang Windows.  If you can find such a function, that method is
easiest for the task.  As I did not, I used the following procedure
instead . . .

3b) If you wrote the other program, like I did, let the Delphi program
continue, but write a message handler like so:

procedure TOpeningScreen.TrapMessages(var Msg: TMsg;
   var Handled: Boolean);  const
 RESULT_OK = $10;
 RESULT_CANCEL = $11;  begin
 if Msg.hWnd = Self.Handle then
 begin
   case Msg.Message of
     RESULT_OK:
       begin
       EndExecOKClick(Self);
       Handled := True;
       end;
     RESULT_CANCEL:
       begin
       EndExecCancelClick(Self);
       Handled := True;
       end;
   end;
 end;
end;

        EndExec???Click reenables all of the buttons, and does a
something different depending on the message.  This way is great because
it allows the executing program to actually pass information BACK to the
calling program.  In my other program (a Visual BASIC one in this case), I
use FindWindow to find the Delphi program's hWnd, and use SendMessage to
send the message in the Form_Close procedure right before exiting.

        Hope that helps!
--

Re:Delphi: Making a shell-program


In a previous article, sve...@oslonett.no (Sven H. Enger) says:

Quote
>Hello!

>I want to make a program that executes an other program and pauses
>until this program ends.

Neil Rubenking wrote a program called In Control using Borland Pascal for
Windows. It is available with full source via FTP with a filename something
along the lines of INCTRL.ZIP. It was first published in PC Magazine July
1992 so is likely to exist in the PCMag area of your FTP site.

Anyway, it contains code that does exactly what you request along with some
other excellent little techniques.

Hope that helps,

Rafe

--
-----------------------------------------------------------------------
 Rafe Aldridge            wWWWWw    Defenestration: n. An annoying act
 r...@rcai.demon.co.uk     o  o     perfected by Micro$oft.
-----------------------ooO-(__)-Ooo------------------------------------

Re:Delphi: Making a shell-program


Sven H. Enger (sve...@oslonett.no) wrote:
: Hello!

: I want to make a program that executes an other program and pauses
: until this program ends.

: By using the function ExecuteFile(...) I can start an other program,
: but the main-program doesn't pause.

: Is there a kind of "modal"-function for a form? Could that be used?

: If there a way to find out what other programs are running at a given
: time, I may use that instead. Is there any?

: Greatfull for any answer; either to this group or by email!

: Sven H. Enger
: sve...@oslonett.no

Here is a snippet of VB code that might help:

Declare Function GetModuleUsage Lib "Kernel" (byVal hInst as Integer) as
                                                                Integer
Sub RunDos(ProgName as string)
   Dim hInst as Integer

   hInst = Shell(prog,7)   ;similar to ExecuteFile??
   do
     i = DoEvents()        ; so we don't hog the cpu
   Loop while GetModuleUsage(hInst) >0

End Sub

Jon

jon.duerd...@sheridanc.on.ca

Re:Delphi: Making a shell-program


Quote
Jon Duerdoth (duerd...@hubble.sheridanc.on.ca) wrote:

: Sven H. Enger (sve...@oslonett.no) wrote:
: : Hello!

: : I want to make a program that executes an other program and pauses
: : until this program ends.

: : By using the function ExecuteFile(...) I can start an other program,
: : but the main-program doesn't pause.

: : Is there a kind of "modal"-function for a form? Could that be used?

: : If there a way to find out what other programs are running at a given
: : time, I may use that instead. Is there any?

: : Greatfull for any answer; either to this group or by email!

: : Sven H. Enger
: : sve...@oslonett.no

: Here is a snippet of VB code that might help:

: Declare Function GetModuleUsage Lib "Kernel" (byVal hInst as Integer) as
:                                                               Integer
: Sub RunDos(ProgName as string)
:    Dim hInst as Integer

:    hInst = Shell(prog,7)   ;similar to ExecuteFile??
:    do
:      i = DoEvents()        ; so we don't hog the cpu
:    Loop while GetModuleUsage(hInst) >0

: End Sub

: Jon

Here is an idea,
In your main application "A", use ShellExec(..) which returns
the handler of the application being launched "B".
Disable your main application "A" (e.g., invisible).
In your application A, use a callback function that will let you
know of all applications termineted (returns the handler).
When handler matches, restore your application "A".

p.s., the callback function is (if I recall) CBTProc ..

I hope this helps. If you still have doubt, e-mail me
and I 'll explain it with an example.

--Fadi

Re:Delphi: Making a shell-program


mikea...@prairienet.org (Michael J. Averbuch) wrote:

Quote
>In a previous article, sve...@oslonett.no (Sven H. Enger) says:
>>Hello!

>>I want to make a program that executes an other program and pauses
>>until this program ends.
>    The problem with that is, as I'm sort of new to Delphi, I don't
>know its equivelent to DoEvents, so I can't yield control to the system
>and not hang Windows.  If you can find such a function, that method is
>easiest for the task.  As I did not, I used the following procedure
>instead . . .

The return value for the WinExec API function is a module handle to
the task, so the way to do this is as follows:

1. Shell using WinExec

2. Loop until GetModuleUsage(module handle) = 0, calling
Application.ProcessMessages for each iteration (this is the DoEvents
equivalent).

HTH

Ian
i...@dircon.co.uk

Re:Delphi: Making a shell-program


Quote
>I want to make a program that executes an other program and pauses
>until this program ends.

See the code below, which I cut from a working program. I learnt how from the
African Chief !  A trap for young players: the constant wm_quit seems not to
be available under Delphi - I had to add it in by hand.

const wm_quit = $0012;
{///////////// a PeekMessage() loop /////////}
procedure Pause;
var
  Msg: TMsg;
Begin
   While PeekMessage (Msg, 0, 0, 0, pm_Remove) do
   begin
       if Msg.Message = wm_Quit then
       begin
          PostQuitMessage(msg.wParam);
          Exit;
       end{Msg.Message};

    if not IsDialogMessage (0, Msg) then
    with Msg do
       begin
         TranslateMessage (Msg);
         DispatchMessage (Msg);
      end{With Msg do};
   end {While PeekMessage};
End {Pause};

{////////// WinExec and Wait //////////////}
Function WinExecWait (PName: PChar; ShowCmd : Integer) : THandle;
Var
  InstanceID : THandle;

Begin
    InstanceID := WinExec (PName, ShowCmd); {call WinExec() }
    WinExecWait := InstanceID;              {return InstanceID }
    if InstanceID <= 32 then Exit;           {some error }

     Repeat
        Pause;   {keep waiting }
     Until GetModuleUsage (InstanceID) = 0; {until this instance ends }
End { WinExecWait() };
{/////////////////////////////////}

{$R *.DFM}

procedure TSDIAppForm.SaveItemClick(Sender: TObject);
begin
WinExecWait ('c:\interact\tablo.pif',sw_show);

{EFFECT OF ABOVE LINE: the Delphi program pauses until the DOS program
tablo.pif has run. Other Windows apps still get a slice of the CPU }

end;

Other Threads